Запись в файл, имя которого является совпадающей строкой в ​​сценарии sed.

Используйте sed с параметром -i , чтобы отредактировать файл на месте. (Резервная копия оригинала будет сохранена как file.txt.bak ). sed -i.bak 's / ^ \ (HOST. * \) / # \ 1 / g 'file.txt

Чтобы прочитать часть регулярного выражения: ^ соответствует началу строки.

() захватывает соответствующий текст во временную внутреннюю переменную ( \ 1 ).

\ необходим перед символами (, так как ваша оболочка украдет их в противном случае.

. * соответствует 0 или более символам.

Итак, начиная с начала строки, она соответствует строке HOST , за которой следует любой текст, вплоть до новой строки. Если строка не соответствует, оставьте как есть.Если он совпадает, то # \ 1 напечатает # , за которым следует текст между () .

1
27.03.2017, 18:45
4 ответа

Есть способ сделать то, что вы хотите, но он работает только с GNU sed.

sed -rn '/TODO/!d 
  :l
  /D\//bw
  N
  bl
  :w
  s/.*TODO *//
  s/\n/ /g
  s_(.*) *D/(.*)_echo \1 >> \2.txt_e
' tasks.txt

Секрет заключается в специальном переключателе e в команде подстановки, которая выполняет содержимое пространства шаблонов как шелл-код. Также обратите внимание на использование -r для группировки.

Кредиты идут на https://stackoverflow.com/questions/14679479/how-can-write-the-multiple-files-with-sed-from-pattern-matched

1
27.01.2020, 23:19

попробуйте это ...

awk '{F=0;for(i=2;i<=NF;i++){if($(i-1)~/TODO/){F=1}if(F){printf("%s ",$i)}}printf("\n")}' RS="D/" tasks.txt | awk '{print > $NF".txt"}'
1
27.01.2020, 23:19

Я думаю, вам действительно стоит написать сценарий. По крайней мере, было бы легче поддерживать и документировать, чем длинную последовательность преобразований sed (но с моей точкой зрения вы можете не согласиться).

Вот предложение Perl:

#!/usr/bin/perl -n
#

sub printTodo {
    my ($todo,$person) = @_;
    my $file;
    open($file, ">>$person.txt");
    print $file "$todo\n";
    close($file);
}

if (/TODO (.*)D\/(\S*)/) {
    printTodo($1,$2);
} elsif (/TODO (.*)/) {
    $found = "$1 ";
} elsif (/(.*)D\/(\S*)/) {
    $found .= $1;
    printTodo($found,$2);
    $found = undef;
} elsif ($found) {
    chomp $_;
    $found .= "$_ ";
}

Предполагая, что вы сохраните этот сценарий как script.pl , а отчет о встрече как meeting , вы бы назвали его так: ./script.pl <встреча .

1
27.01.2020, 23:19

Perl

Slurp tasks.txt и просмотрите строки, начинающиеся с TODO , и найдите ближайший D / , и мы даже можем перепрыгнуть через новые строки, чтобы в этом возникает необходимость. м // с .

Новая особенность заключается в том, что если бы мы запускали эту вещь во второй раз, то сгенерированные файлы *. Txt не добавлялись, а запускались заново при каждом запуске. Следовательно, по своей конструкции они никогда не столкнутся с синдромом беглого размера.

perl -MFatal=open -l -0777ne '
  do{open my $fh, $h{$2}++ ? ">>" : ">", "$2.txt"; print $fh $1 =~ y/\n/ /rs}
     while m|\bTODO\s*(.+?)\s*D/(\S+)|sg' tasks.txt

sed + ed

Как обычно в таких случаях, мы динамически создаем код ed для получения вывода. Что нового в этом сценарии, так это то, что файл данных, с которым будет работать код ed , сам динамически генерируется из того же ввода.

Это похоже на то, что данные + код находятся внутри файла data.txt, который разделяется, а затем объединяется в качестве входных данных ed для генерации вывода из ed .

sed -n '
   /TODO/!d
   :l
   /D\//bw
   N
   bl
   :w
   s/.*TODO *//
   s/\n/ /g
  #<----------------------- ORIG --------------------->#

   H;s| *D/.*||w /tmp/data.txt
   g;s/.*\n//;x;s/\(.*\)\n.*/\1/;x

   G;s/\n/&&/
   h
   / *D\/\(.*\)\n\(\(.*\n\)\{0,\}\)\1\n/!{
   s/.*[^ ] *D\/\(.*\n\)\n/\1/
   x
   s/\n\n.*//
   s|\(.*[^ ]\) *D/|/\1/w |;s|$|.txt|p;$!d;s/.*/q/p;q
   }

   g
   s/\n\n.*//
   s|\(.*[^ ]\) *D/|/\1/W |;s|$|.txt|p;$!d;s/.*/q/p;q
' tasks.txt | ed -s - /tmp/data.txt

Предупреждение:

Убедитесь, что имя человека, которому назначена задача, не называется «задачи».

1
27.01.2020, 23:19

Теги

Похожие вопросы