Как добавить строку в файл с помощью Perl?

Здравствуйте.
Вопрос вроде бы простой, но победить никак не могу.

Имеется текстовый файл users.list содержащий разделы с перечнем пользователей:
<Title1>
username1
username2
<Title2>
username2
username3

С помощью перл скрипта необходимо добавить пользователя username4 в раздел Title1, при этом не перезаписав уже имеющихся пользователей.
Мой скрипт:
#!/usr/bin/perl -w
use strict;
use warnings;
if(open(FILE, "+< users.list") or die "Error: $!"){
    flock(FILE, 2);
}
while(<FILE>){
    if(~/Title1/){
        print FILE "username4";
        last;
    }
}
close(FILE);

В данном варианте произойдет перезапись username1 на username4. Пробовал добавлять символы переноса строки и возвращения каретки, но результат не тот что нужно.

П.С. Про вариант "перегнать в массив и обратно" думал, но хочется узнать, можно ли реализовать без массива.
  • Вопрос задан
  • 436 просмотров
Пригласить эксперта
Ответы на вопрос 2
alsopub
@alsopub
Без массива.

Читать по одной строке из файла, записывать по одной строке во временный файл.
Когда встретится нужный раздел - записать во временный файл дополнительную строку.
Переименовать временный файл в исходный.
Временный файл лучше разместить рядом (в том же каталоге) чтобы сработал rename.

Мне кажется если в вашем примере заменить "username4" на "u4" то получится каша.
Файлы нельзя просто так взять и "растянуть" или "сжать" в середине.
Максимум что можно сделать - обрезать с конца или дописать в конец.
Ответ написан
@hobo-mts
Shortly
#!/usr/bin/perl

use strict;
use warnings;

while (<>) {
    print;
    last if /<Title1>/i;
}
while (<>) {
    if (/<Title/i) {
        print "username4\n";
        print;
        last;
    }
    else {
        print;
    }
}
print while <>;

Использование:
mv users.list users.list.bak && ./users.pl <users.list.bak >users.list

Если файл небольшой, то можно проще:
mv users.list users.list.bak && perl -e '(my $ss = join "", <>) =~ s/(<Title1>[^<]+)(.+)/$1username4\n$2/is; print $ss;' <users.list.bak >users.list

Или:
$ perl -e '$/ = ""; <> =~ /(<Title1>[^<]+)(.+)/is && print $1, "user4\n", $2;' <users.list
<Title1>
username1
username2
username4
user4
<Title2>
username2
username3
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы