我正在尝试标记颜色标记内的所有内容,并将其替换为其他内容,例如:
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的任何想法?
答案 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}}表示匹配应该是非贪婪的。
如果您在(.*)
后跳过?
,则此处是您当前必须获得的输出:
.*