我有一个文本文件,我想更换内部的所有空间[[,并]]用连字符(括号中从来没有嵌套,总是匹配)。下面是一个例子:
$ cat test.txt
abc [[foo]] xyz
abc [[foo bar]] xyz
abc [[foo bar baz]] xyz [[something else]]
Run Code Online (Sandbox Code Playgroud)
所以所需的输出是:
abc [[foo]] xyz
abc [[foo-bar]] xyz
abc [[foo-bar-baz]] xyz [[something-else]]
Run Code Online (Sandbox Code Playgroud)
我想我可以sed用来匹配括号内的字符串,然后使用该e标志sed再次运行结果以进行替换。然而,问题是不仅匹配的字符串被作为命令执行,而且整个模式空间(似乎是整行):
$ sed -E 's@(\[\[)(.+)(\]\])@sed -e "s/ /-/g" <<< "\1\2\3"@gpe' test.txt
abc sed -e "s/ /-/g" <<< "[[foo]]" xyz
sh: 1: Syntax error: redirection unexpected
abc sed -e "s/ /-/g" <<< "[[foo bar]]" xyz
sh: 1: Syntax error: redirection unexpected
abc sed -e "s/ /-/g" <<< "[[foo bar baz]]" xyz
sh: 1: Syntax error: redirection unexpected
Run Code Online (Sandbox Code Playgroud)
有没有办法将通过e标志执行的内容限制为匹配的字符串?如果没有,我将如何解决这个问题sed?
我认为没有办法限制e修饰符传递给 shell 的内容;但是你可以做这样的事情:
$ sed -E ':a;s@(.*\[\[)([^][]* [^][]*)(\]\].*)@printf "%s%s%s" "\1" "$(printf "\2" | sed "s/ /-/g")" "\3"@e;ta' test.txt
abc [[foo]] xyz
abc [[foo-bar]] xyz
abc [[foo-bar-baz]] xyz [[something-else]]
Run Code Online (Sandbox Code Playgroud)
请注意,多个替换的处理是通过循环完成的 - 由于匹配的贪婪,它实际上以相反的顺序进行替换。
还要注意e的用途/bin/sh,这将有可能不支持<<<输入重定向(因此使用的管道当量printf "\2" | sed "s/ /-/g")。
如果 perl 是一个选项,您可以做一些更接近您的原始意图的事情,例如:
$ perl -pe 's/(?<=\[\[)(.*?)(?=\]\])/$1 =~ s: :-:rg/ge' test.txt
abc [[foo]] xyz
abc [[foo-bar]] xyz
abc [[foo-bar-baz]] xyz [[something-else]]
Run Code Online (Sandbox Code Playgroud)
由于 perl 提供了一个非贪婪的修饰符?,这可以更传统地使用g外部替换上的标志来处理每行的多个替换。
| 归档时间: |
|
| 查看次数: |
103 次 |
| 最近记录: |