我想在两个字符串之间替换一个未知字符串。
(1(...) 2(...) 3(...))
我使用:
sed -i "s/2(.*)/2(new)/g"
但我得到了。(需要最后一个(
(1(hello) 2(new)
我想要:
(1(...) 2(new) 3(...))
有人能帮我吗?
编辑:
感谢回答者,我有另一个案例:
"data_1": [...], "data_2": [...], "data_3": [...]
我想在"one_answers"之间插入一个字符串;data_ 2":['和数据_2 后首次出现的']'
sed
使用贪婪匹配,因此OP的尝试2(.*)
将匹配第一个文本2(
加上以)
结尾的最长字符串;考虑以下情况,我们的比赛从第一个2(
开始,一直进行到最后一个)
:
$ echo '(1(...) 2(...) 3(...) 2(abc) 4(...)) more stuff' | sed 's/2(.*)/2(new)/'
(1(...) 2(new) more stuff
为了将匹配限制为第一个匹配的)
,有几种方法,其中一种想法是明确哪些匹配,哪些不匹配,请考虑:
$ echo '(1(...) 2(...) 3(...) 2(abc) 4(...)) more stuff' | sed 's/2([^)]*)/2(new)/'
(1(...) 2(new) 3(...) 2(abc) 4(...)) more stuff
在这种情况下,我们使用2([^)]*)
,它表示在2(
上匹配,然后是任何数量的字符,这些字符不是)
([^)]*
(,然后是)
。
为了匹配2(...)
的所有非贪婪出现(其中...
表示任何非)
字符(,我们可以在sed
脚本的末尾添加g
全局限定符,例如:
$ echo '(1(...) 2(...) 3(...) 2(abc) 4(...)) more stuff' | sed 's/2([^)]*)/2(new)/g'
(1(...) 2(new) 3(...) 2(new) 4(...)) more stuff
尝试:
echo '(1(...) 2(...) 3(...))' | sed 's/2((.*))/2(new)/g'
您需要转义正在使用的括号。以匹配
更新:来自Benjamin W的评论
echo '(1(...) 2(TIM) 3(...))' | sed -E 's/2([^)]*)/2(new)/g'
我尝试过用sed
找到非贪婪模式匹配的破解解决方案,但发现perl
通常看起来更容易完成任务。
除非您对仅使用sed
有特定的限制,否则您可以:
echo "(1(...) 2(...) 3(...))" | perl -pe "s/2(.*?)/2(new)/g"
正则表达式中唯一的区别是.*
之后的?
非贪婪修饰符,它与第一个)
匹配。
此处详细介绍了命令行选项。这里引用了非贪婪修饰符。