【问题标题】:Insert content from a file after specific pattern regex match by using sed in bash在 bash 中使用 sed 在特定模式正则表达式匹配后插入文件中的内容
【发布时间】:2019-05-12 06:49:02
【问题描述】:

我想在特定文本之前插入文本文件中的多行。我想用正则表达式选择特定的文本,文本是这样的:

//**insert_yannyann*//

『//**insert_yanyann*//』在b.txt中,b.txt就是这样

...

//**insert_yannyann*//

...

a.txt 是这样的:

1234
5678
9101

为了在 b.txt 的文本模式之前插入 a.txt 文本文件,我在 ubuntu 18.04 bash 命令中尝试了这个正则表达式。

sed -n -i -e '\/\/**insert_yannyann*\/\/ /r a.txt' -e 1x -e '2,${x;p}' -e '${x;p}' b.txt

即使我尝试了另一种正则表达式模式。

sed -n -i -e '//?\s*\*[(?=.*\insert_yannyann\b)]*?\*\s*//? /r a.txt' -e 1x -e '2,${x;p}' -e '${x;p}' b.txt

但是 sed 总是因为我使用了错误的正则表达式而向我显示错误消息。

我想让 b.txt 变成这样:

...

1234
5678
9101
//**insert_yannyann*//

...

我肯定会通过一些在线正则表达式工具检查其中两个正则表达式是否正确,但我不明白为什么 sed 向我显示错误消息。

\/\/**insert_yannyann*\/\/

//?\s*\*[(?=.*\insert_yannyann\b)]*?\*\s*//?

我不确定正则表达式规则在不同的编程语言中是否相同,有人可以解释为什么它不正确吗?

【问题讨论】:

  • 关于online regex tools 它们不适合sed,因为正则表达式功能和语法非常不同.. 例如:sed 不支持环视
  • 哦~,我明白了,所以我最好尝试另一种方法来达到同样的效果?
  • 上面提到的重复问题中建议了多种方式,如果你知道要匹配的行不能是文件中的最后一行,我觉得sed -e '\,//\*\*insert_yannyann\*//, { r a.txt' -e 'N}'是个不错的选择
  • 嗯嗯嗯,好的。但我发现使用 {} 将文件与正则表达式分开比使用“/xxx/xxx/”更好,对吗?

标签: regex sed


【解决方案1】:

Perl 可能不是您的选择,但值得一试。 使用 Perl 你可以说:

perl -0777 -ne 'if ($. == 1) {$replace = $_; next} s#(?=//\*\*insert_yannyann\*//)#$replace#g; print' a.txt b.txt > b_new.txt

然后b_new.txt 成立:

...

1234
5678
9101
//**insert_yannyann*//

...

说明:

  • -0777 选项会导致 Perl 一次性吞下整个文件。
  • Perl 变量 $. 保存输入行号,在此用例中与输入文件号等效。有了这个值,我们可以切换a.txtb.txt 的处理。
  • $replace = $_ 语句将变量$replace 赋给a.txt 的内容。
  • 最重要的部分将是正则表达式s#(?=//\*\*insert_yannyann\*//)#$replace#gPerl 正则表达式支持带有 (?=pattern) 表示法的前瞻断言。借助此功能,我们可以轻松地在指定模式之前插入内容。

希望这会有所帮助。

编辑

使用 AWK,您可以做类似的事情:

awk 'NR==FNR {replace = replace $0 RS; next}
    {text = text $0 RS}
    END {
        print gensub(/\/\/\*\*insert_yannyann\*\/\//, replace "&", "g", text)
    }' a.txt b.txt > b_new.txt

关键是替换字符串(gensub() 的第二个参数)是replace、a.txt 的内容和代表正则表达式匹配字符串的& 的串联。将变量 replace 放在 & 之前会导致替换之前匹配的模式。

【讨论】:

  • 哦!我知道了。但我还有一个问题。是否有 awk,grep 也支持查找功能或只有 perl 可以做到这一点?
  • 许多其他语言(PHP、ruby、python ..)和一些工具(grep、find ..)支持lookaround in regex。虽然 AWK 不支持它,但我们可以做同样的事情。我已经在我的答案中添加了这个例子。事实上,lookahead assertion 功能对于我上面的脚本并不是必需的,因为它会在 应用正则表达式的模式匹配之前删除所有行。从严格意义上讲,lookahead 在逐行处理中就像是根据下一个(未读)行做出决定,我的用法并不适用。
  • 哦!我得到了它!抱歉我最近在工作的回复晚了……在某些严格的条件下,使用“相同模式”方法比前瞻性方法更安全。谢谢你教我这个东西!
  • 请注意,gensub() 是 GNU awk 扩展。
猜你喜欢
  • 2013-05-18
  • 2015-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多