2

假设我有以下文字:

name is test1 and age is test2 end
name is test3 and age is test4 end
name is test5 and age is test6 end
name is test7 and age is test8 end

我正在寻找 test1,test2,...,如下所示:

-bash$ grep -o -P "is .*? and|is .*? end" test
is test1 and
is test2 end
is test3 and
is test4 end
is test5 and
is test6 end
is test7 and
is test8 end

有没有办法可以在匹配的模式前添加一些文本?我正在寻找这样的输出:

STRING1:is test1 and
STRING2:is test2 end
STRING1:is test3 and
STRING2:is test4 end
STRING1:is test5 and
STRING2:is test6 end
STRING1:is test7 and
STRING2:is test8 end
4

3 回答 3

3

您可以sed在管道中使用(诚然它不是很干净):

$ grep -o -P "is .*? and|is .*? end" test | sed '/and$/s/^/STRING1:/; /end$/s/^/STRING2:/'
STRING1:is test1 and
STRING2:is test2 end
STRING1:is test3 and
STRING2:is test4 end
STRING1:is test5 and
STRING2:is test6 end
STRING1:is test7 and
STRING2:is test8 end

before 每个替换将/.nd$/替换限制在与该正则表达式匹配的行上。

于 2012-05-06T07:58:28.697 回答
3

我将 grep 的输出通过管道传输到 awk 以满足您的需求:

grep -o -P "is .*? and|is .*? end" test | \
awk -v a=STRING1: -v b=STRING2: "/and$/ {print a\$0} /end$/ {print b\$0}"
于 2012-05-06T08:07:55.100 回答
0

由于您要操作而不仅仅是选择文本,sed因此比grep.

构造一个执行您想要的替换的正则表达式很简单。您有两个替换,因此您可以使用两个表达式 ( -e)。要仅对匹配的行进行操作(就像您的 grep 示例一样),请使用sed -nandp操作仅打印匹配的行。棘手的部分是您想在同一行上多次操作,但是当您执行第一次替换时,您会丢失字符串的其余部分以进行第二次替换。例如,以下内容接近您想要的,但第二个表达式永远不会匹配,因为第一个表达式删除了第二个表达式匹配的字符串:

sed -n -e 's/.*\(is .* and\).*/STRING1:\1/p' -e 's/.*\(is .* end\)/STRING2:\1/p'
STRING1:is test1 and
STRING1:is test3 and
STRING1:is test5 and
STRING1:is test7 and

为了解决这个问题,您可以使用hgsed 命令将模式空间(输入行)复制到保持缓冲区 ( h) 中,并将其复制回模式空间以供下一个 sed 命令 ( g):

sed -n -e 'h;s/.*\(is .* and\).*/STRING1:\1/p' -e 'g;s/.*\(is .* end\)/STRING2:\1/p'
STRING1:is test1 and
STRING2:is test2 end
STRING1:is test3 and
STRING2:is test4 end
STRING1:is test5 and
STRING2:is test6 end
STRING1:is test7 and
STRING2:is test8 end

在执行第一个表达式中的替换之前,该行被保存在保持缓冲区中。第二个表达式首先使用保持缓冲区加载模式缓冲区,以便第二个替换可以工作。

您可以将这两个单独的表达式合二为一,但我认为这会使其更难阅读:

sed -n -e 'h;s/.*\(is .* and\).*/STRING1:\1/p;g;s/.*\(is .* end\).*/STRING2:\1/p'
于 2012-05-06T12:31:29.477 回答