我有包含要完成的任务的会议协议,每个协议都以关键字开头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
以便能够使用分组。
答案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
珀尔
Slurp
tasks.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”。