我正在寻找一个sed
命令来匹配保留空间的内容和模式空间。例如,假设假设的{h}
标记引用保留空间的内容:
echo "foo: one foo three" | sed -n \
-e 'h; s/^\(.*\):.*$/\1/' \
-e 'x; s/.*: \(.*\)$/\1/' \
-e '/{h}/ p'
第一个-e
将整个echo
放入保留空间,然后将模式空间缩小到最初的“foo”。第二个-e
将“foo”交换到保留空间,并将原始echo
缩减为尾随“一个foo 3”。第三个(假设的)-e
尝试将保持空间“foo”与模式空间“one foo three”匹配。当然没有这样的标记{h}
,但如果有,则模式空间匹配,输出为:
one foo three
sed
是否提供了任何方法来执行此操作?
我的目标是在一个大文件中计算所有这些匹配(4MB)。也可以使用while read
循环来完成它,但它需要每行至少启动3个子进程,结果非常慢!如果sed
不这样做,欢迎提出任何建议。
答案 0 :(得分:4)
这是sed解决方案:
sed -ne '/^\([^:]*\):.*\1/ p' infile
假设infile
包含内容:
foo: one foo three
foo: one loo three
troo: one foo three
three: one foo three
它产生:
foo: one foo three
three: one foo three
答案 1 :(得分:3)
这不是sed
,但有些人喜欢这样吗?
echo "foo: one foo three" | awk -F": " '$2~$1 {print $2}'
one foo three
答案 2 :(得分:0)
如所示,此特定任务的“正确”(最简单)方法是完全不使用保留空间进行匹配。
但是,对于一个有趣的练习,如果您真的必须使用保留空间(也许作为更复杂的sed程序的一部分)怎么办?
假设保留空间不包含任何\n
(就像上面原始问题中的情况一样),则可以进行以下操作:
-e 'H;g;s/^\([^\n]*\)\n\(.*\1.*\)/\2/p'
这会将模式空间附加到保留空间(由\n
分隔),然后将其复制回模式空间,并使第一行(即原始保留空间)与其余行(即原始图案空间)。如果发生匹配,则通过丢弃第一行来恢复原始模式空间,然后打印结果。
(请注意,没有要求在单词边界内进行匹配,甚至不要求保持空间只有一个单词。例如,保持空间中的foo bar
将与loofoo barzoo
匹配如果不希望这样,可以在上面的\b
之前和之后添加\1
来解决问题。)
要扩展乐趣,我们还需要保留原始的保留空间,以便将来在同一sed程序中进行比赛。为此,在上面的代码之后,我们将再次将修改后的保留空间复制到模式空间,然后丢弃除第一行(即原始保留空间)以外的所有内容,然后将其放回保留空间:< / p>
-e 'g;s/\n.*//;h'
将所有问题汇总在一起,完整的sed命令将是:
echo "foo: one foo three" | sed -n \
-e 'h; s/^\(.*\):.*$/\1/' \
-e 'x; s/.*: \(.*\)$/\1/' \
-e 'H; g; s/^\([^\n]*\)\n\(.*\1.*\)/\2/p' \
-e 'g; s/\n.*//; h'
(您会看到为什么严格在原始问题的范围内这不是最佳方法。同样在原始问题的范围内,最后一个-e
并没有任何用处并且可以省略。)