3

我正在寻找一个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为尾随的“one foo three”。第三个(假设的)-e尝试将保持空间“foo”与模式空间“one foo three”进行匹配。当然没有这样的 token {h},但如果有,模式空间会匹配,输出将是:

one foo three

是否sed提供任何方法来做到这一点?

我的目标是在一个大文件 (4MB) 中计算所有此类匹配项。它也可以通过while read循环来完成,但它需要每行至少启动 3 个子进程,结果证明这非常慢!如果sed只是不这样做,欢迎提出任何建议。

4

3 回答 3

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
于 2013-10-02T21:59:03.430 回答
3

这不是sed,但有些像这样?

echo "foo: one foo three" | awk -F": " '$2~$1 {print $2}'
one foo three
于 2013-10-02T21:09:31.037 回答
0

正如已经展示的那样,这个特定任务的“正确”(最简单)方法是在完全不使用保持空间的情况下进行匹配。

但是,为了一个有趣的练习,如果你真的必须使用保持空间(也许作为更复杂的 sed 程序的一部分)怎么办?

假设保留空间不包含任何内容\n(如上面原始问题中的情况),以下将起作用:

-e 'H;g;s/^\([^\n]*\)\n\(.*\1.*\)/\2/p'

这会将模式空间附加到保持空间(由 分隔\n),然后将其复制回模式空间,并将第一行(即原始保持空间)与其余行(即原始模式空间)进行匹配。如果发生匹配,则通过丢弃其第一行来恢复原始模式空间,然后打印结果。

(请注意,没有要求匹配发生在单词边界内 - 甚至保留空间是否只有一个单词。例如,foo bar在保留空间中将匹配loofoo barzoo模式空间。如果不希望这样做,添加\b之前在\1上面应该做的伎俩。)

为了增加乐趣,我们还要求在同一个 sed 程序中为将来的匹配保留原始保持空间。为了做到这一点,在上面的代码之后,我们将修改后的保持空间再次复制到模式空间,然后丢弃除第一行之外的所有内容(即原始保持空间),然后将其放回保持空间:

-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没有做任何有用的事情,可以省略。)

于 2020-10-25T08:11:02.463 回答