2013-05-30 200 views
5

我有一个包含行的文件像替换/在sed

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

我试图删除*内<>但不应超出删除匹配的字符串中的特殊字符。标签可能比以上更复杂。例如,<*better *tag 1>

我试过/\bregex\b/s/\*//g,它适用于标签1,但不适用于标签2.那么我怎样才能使它适用于标签2呢?

非常感谢。

+0

你能有嵌套'<>'? –

+0

在我的情况下,不会有嵌套的<>。干杯。 – ToonZ

回答

3

强制性Perl的解决方案:

perl -pe '$_ = join "", 
     map +($i++ % 2 == 0 ? $_ : s/\*//gr), 
     split /(<[^>]+>)/, $_;' FILE 

附加:

+0

+1的单行划线器 –

+0

伟大的perl单线程。我也是+1。 – ToonZ

3

简单的解决方案,如果您有标签只有一个星号

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

如果你可以有更多的,你可以使用SED转到标签系统

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. 
+0

感谢您的循环解决方案。 :-) – ToonZ

+0

你问sed解决方案:)我很高兴它帮助你;) – bartimar

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> 
+0

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