珀尔

珀尔

我有包含要完成的任务的会议协议,每个协议都以关键字开头TODO并以 结尾D/nameOfAssignee,如下所示:

Meeting 2017/03/22
some stuff
TODO task for philipp D/philipp

some more stuff

TODO task for jane D/jane
TODO task for joe D/joe

some other stuff TODO Another
task for Philipp
D/philipp

still
more
stuff

TODO Yet another
task for jane   D/jane

现在我想获取一个文件philipp.txt

task for philipp
Another task for Philipp

和一个文件jane.txt

task for jane
Yet another task for jane

和一个文件joe.txt

task for joe

我用以下方法做到这一点sed

sed -n '/TODO/!d
  :l
  /D\//bw
  N
  bl
  :w
  s/.*TODO *//
  s/\n/ /g
  s_ *D/philipp__w philipp.txt
  s_ *D/joe__w joe.txt
  s_ *D/jane__w jane.txt
' tasks.txt

这可行,但对于每个可能的受让人,我需要在脚本中使用相同的行,这开始变得烦人。在文档中,我找不到在文件名中使用正则表达式匹配的子字符串的方法,例如:

s_ *D/\(.*\)__w \1.txt (这不起作用!所有内容都写入名为 的文件中\1!)

是否还有另一种可能性,首先生成我可以在第二次运行中使用的脚本,并为每个受让人自动生成这些行?

或者只是sed错误的工具,我应该在 中做这样的事情吗python

答案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替换命令中的特殊开关,它将模式空间的内容作为 shell 代码执行。另请注意使用-r以便能够使用分组。

积分转到https://stackoverflow.com/questions/14679479/how-can-write-the-multiple-files-with-sed-from-pattern-matched

答案2

尝试这个...

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"}'

答案3

我认为你确实应该写一个脚本。它至少比一长串 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 < meeting

答案4

珀尔

Slurptasks.txt 并查看以 开头的字符串TODO并查找最近的D/字符串,我们甚至可能会跳过换行符,以便需要这样做。m//s

一个新颖的功能是,如果我们第二次运行这个东西,那么生成的*.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 中找到 data+code 一样,这些数据被分开,然后作为 的输入汇集在一起​​,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

警告:

确保分配任务的人员名称中没有名为“tasks”。

相关内容