sed:匹配模式空间的保持空间

时间:2013-10-02 20:44:53

标签: recursion sed pattern-matching

我正在寻找一个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不这样做,欢迎提出任何建议。

3 个答案:

答案 0 :(得分:4)

这是解决方案:

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并没有任何用处并且可以省略。)