替换bash中两个字符串之间的未知字符串



我想在两个字符串之间替换一个未知字符串。

(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"

正则表达式中唯一的区别是.*之后的?非贪婪修饰符,它与第一个)匹配。

此处详细介绍了命令行选项。这里引用了非贪婪修饰符。

最新更新