sed替换两个字符串之间的通配符

时间:2015-01-12 01:10:33

标签: regex bash sed wildcard non-greedy

我正在尝试标记颜色标记内的所有内容,并将其替换为其他内容,例如:

I have a [color=blue]dog[/color] and a [color=blue]cat[/color] in my house.

I have a [color=blue][b]foobar[/b][/color] and a [color=blue][b]foobar[/b][/color] in my house.

以下是我尝试的内容:

sample='I have a [color=blue]dog[/color] and a [color=blue]cat[/color] in my house.'
replace='foobar'
sample=$(echo $sample| sed "s/\[color=blue\].*\[\/color\]/\[color=blue\]\[b\]$replace\[\/b\]\[\/color\]/g")

哪个让我:

I have a [color=blue][b]foobar[/b][/color] in my house.

关于如何在这种情况下使用sed nongreedy的任何想法?

6 个答案:

答案 0 :(得分:1)

只需将.*替换为[^[]*(左括号以外的任何字符)。那就是:

"s/\[color=blue\][^[]*\[\/color\]/\[color=blue\]\[b\]$replace\[\/b\]\[\/color\]/g"

答案 1 :(得分:1)

sed总是很贪心。你可以仔细选择正则表达式来解决它。以下示例与您的相同,只是.*已替换为[^[]*(这意味着所有除了 [):

$ echo $sample| sed "s/\[color=blue\][^[]*\[\/color\]/\[color=blue\]\[b\]$replace\[\/b\]\[\/color\]/g"
I have a [color=blue][b]foobar[/b][/color] and a [color=blue][b]foobar[/b][/color] in my house.

对于真正非贪婪的正则表达式,请尝试使用perl或python。

答案 2 :(得分:0)

  sed 's#\(\[color=[[:alpha:]]*\]\)[[:alnum:]]*\(\[/color\)#\1[b]foobar[/b]\2#g'

例如

echo 'I have a [color=blue]dog[/color] and a [color=blue]cat[/color] in my house.'|sed 's#\(\[color=[[:alpha:]]*\]\)[[:alnum:]]*\(\[/color\)#\1[b]\2#g'

输出

  I have a [color=blue][b]foobar[/b][/color] and a [color=blue][b]foobar[/b][/color] in my house.

答案 3 :(得分:0)

sed -r 's/(\[color=[a-z]*\])[a-z]*(\[\/color\])/\1[b]foobar[\/b]\2/g' File

sed 's/\(\[color=[a-z]*\]\)[a-z]*\(\[\/color\]\)/\1[b]foobar[\/b]\2/g' File

<强>说明: 在这里,我们使用1. [color=any small letter sequence]2. any small letter sequence查找模式3. [/color],后跟1 and 3后跟(和组模式)。然后我们做替换。我们保留1st and 2nd groups(使用\1\2),但使用[b]foobar[/b]替换第一组和第二组之间的内容。

答案 4 :(得分:0)


正如其他人所说,你需要通过阅读不匹配的字符来使用非贪婪。

在括号[^ABC]中使用克拉实际上不代表随后的任何内容。

因此,将此项与星号*一起使用只会匹配该字符的下一个字符。


例如

[^[]*

将所有内容都匹配到下一个[括号

此外,每个人都反斜杠逃避替换,因为它无法打印正则表达式而无需更换。

无论如何,这是一个应该有效的命令。

sed 's/\(\[color[^]]*\]\)[^[]*\(\[\/color\]\)/\1[b]foobar\[b]\2/g'

答案 5 :(得分:0)

sed永远是贪婪的。如果您严格要求非贪婪的变体,则可以使用perl

$ echo $test
I have a [color=blue]dog[/color] and a [color=blue]cat[/color] in my house.

$ perl -pne 's/(\[color=[a-zA-Z]*\])(.*?)(\[\/color\])/$1\[b\]foobar\[\/b\]$3/g' <<< "$test"
I have a [color=blue][b]foobar[/b][/color] and a [color=blue][b]foobar[/b][/color] in my house.

我想,你可以在这里解释大部分正则表达式,除了微小的语法变化:
代替(.*?)的{​​{1}}表示匹配应该是非贪婪的。
如果您在(.*)后跳过?,则此处是您当前必须获得的输出:

.*
相关问题