在sed中替换/删除匹配字符串中的特殊字符

5

我有一个包含以下内容的文件

I want a lot <*tag 1> more <*tag 2>*cheese *cakes.

我正在尝试删除<>内部的*,但不是在外面。标签可能比上面更复杂。例如:<*better *tag 1>
我尝试了/\bregex\b/s/\*//g,它适用于标签1,但不适用于标签2。所以我该如何使其对标记2也起作用?
非常感谢。

你可以有嵌套的 <> 吗? - Carl Norum
在我的情况下,不会有嵌套的<>符号。祝好! - ToonZ
3个回答

3

如果标签中只有一个星号,那么解决方案就很简单。

sed 's/<\([^>]*\)\*\([^>]*\)>/<\1\2>/g'

如果你需要更多的话,可以使用sed goto label系统。
sed ':doagain s/<\([^>]*\)\*\([^>]*\)>/<\1\2>/g; t doagain'

doagain是循环的标签,t doagain是有条件跳转到标签doagain。请参考sed手册:

t label

 Branch to label only if there has been a successful substitution since the last 
 input line was read or conditional branch was taken. The label may be omitted, in 
 which case the next cycle is started.

感谢您提供的循环解决方案。 :-) - ToonZ
你要求sed解决方案 :) 很高兴它能帮到你 ;) - bartimar

3
必需的Perl解决方案:
perl -pe '$_ = join "",
        map +($i++ % 2 == 0 ? $_ : s/\*//gr),
        split /(<[^>]+>)/, $_;' FILE

添加:

perl -pe 's/(<[^>]+>)/$1 =~ s(\*)()gr/ge' FILE

伟大的 Perl 一行代码。我也点赞。 - ToonZ

1
"awk可以解决你的问题:"
awk '{x=split($0,a,/<[^>]*>/,s);for(i in s)gsub(/\*/,"",s[i]);for(j=1;j<=x;j++)r=r a[j] s[j]; print r}' file

抱歉,您需要提供要翻译的具体文本才能进行翻译。
 awk '{x=split($0,a,/<[^>]*>/,s)
       for(i in s)gsub(/\*/,"",s[i])
       for(j=1;j<=x;j++)r=r a[j] s[j]
       print r}' file

测试您的数据:

kent$  cat file
I want a lot <*tag 1> more <*tag 2>*cheese *cakes. <*better *tag X*>

kent$  awk '{x=split($0,a,/<[^>]*>/,s);for(i in s)gsub(/\*/,"",s[i]);for(j=1;j<=x;j++)r=r a[j] s[j]; print r}' file
I want a lot <tag 1> more <tag 2>*cheese *cakes. <better tag X>

我不熟悉split的四个参数版本,第四个参数是什么? - Lorkenpeist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接