Используйте sed с параметром -i
, чтобы отредактировать файл на месте. (Резервная копия оригинала будет сохранена как file.txt.bak
).
sed -i.bak 's / ^ \ (HOST. * \) / # \ 1 / g 'file.txt
Чтобы прочитать часть регулярного выражения:
^
соответствует началу строки.
()
захватывает соответствующий текст во временную внутреннюю переменную ( \ 1
).
\
необходим перед символами (
, так как ваша оболочка украдет их в противном случае.
. *
соответствует 0 или более символам.
Итак, начиная с начала строки, она соответствует строке HOST
, за которой следует любой текст, вплоть до новой строки. Если строка не соответствует, оставьте как есть.Если он совпадает, то # \ 1
напечатает #
, за которым следует текст между ()
.
Есть способ сделать то, что вы хотите, но он работает только с 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
попробуйте это ...
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"}'
Я думаю, вам действительно стоит написать сценарий. По крайней мере, было бы легче поддерживать и документировать, чем длинную последовательность преобразований 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 <встреча
.
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
Как обычно в таких случаях, мы динамически создаем код 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
Убедитесь, что имя человека, которому назначена задача, не называется «задачи».