如何使用sed寻找前进和替换所选字符

时间:2012-11-21 08:21:25

标签: regex replace sed

我可以使用sed替换所选字符,例如H => X1 => 2,但首先向前搜索,以便不替换第一组中的字符。

示例数据:

"Hello World";"Number 1 is there";"tH1s-Has,1,HHunKnownData";

sed之后应如何:

"Hello World";"Number 1 is there";"tX2s-Xas,2,XXunKnownData";

我尝试过:

没什么,我会尝试,但我所知道的关于sed表达式的一切似乎都是错误的。

好的,我试图捕获([^;]+)和“跳过”(使用'\ 1 \ 2'...... 让我们回来)第一组以;分隔,这工作正常,但后来出现问题,如果我使用捕获我需要选择整个组,如果我不使用捕获,我将丢失数据。

5 个答案:

答案 0 :(得分:1)

如果awk对你没问题:

awk -F";" '{gsub("H","X",$3);gsub("1","2",$3);}1' OFS=";" file

使用-F,文件以分号分隔为分隔符,因此现在第3个字段($ 3)是我们感兴趣的。 gsub函数用第3个字段中的X替换所有出现的H,再次1到2。

1是打印每一行。

答案 1 :(得分:1)

<强> [UPDATE]

(我刚才意识到它可能会更短.Perl有一个自动分割模式):

$F[2] =~ s/H/X/g; $F[2] =~ s/1/2/g; $_=join(";",@F)

Perl的特别可读性并不为人所知,但在这种情况下,我怀疑使用sed获得的最佳效果可能不如Perl那么清晰:

echo '"Hello World";"Number 1 is there";"tH1s-Has,1,HHunKnownData";' | 
  perl -F';' -ape '$F[2] =~ s/H/X/g; $F[2] =~ s/1/2/g; $_=join(";",@F)'

拆开Perl代码:

# your groups are in @F, accessed as $F[$i]
$F[2] =~ s/H/X/g;      # Do whatever you want with your chosen (Nth) group.
$F[2] =~ s/1/2/g; 
$_ = join(";", @F)     # Put them back together.

perl -pesed类似。 (有点。)

perl -F';' -ape表示使用自动拆分(-a)并将字段分隔符设置为';'。然后,您可以通过$F[i]访问您的论坛 - 因此它的工作方式也类似于awk

所以它也会像perl -F';' -ape '/*your code*/' < inputfile

一样工作

我知道您要求sed解决方案 - 我经常发现自己会转换为Perl(虽然我仍然喜欢sed),但我会选择单行。

答案 2 :(得分:1)

sed可以实现这一点,但有点单调乏味。要在字段编号$FIELD进行翻译,您可以使用以下内容:

sed 's/\(\([^;]*;\)\{'$((FIELD-1))'\}\)\([^;]*;\)/\1\n\3\n/;h;s/[^\n]*\n\([^\n]*\).*/\1/;y/H1/X2/;G;s/\([^\n]*\)\n\([^\n]*\)\n\([^\n]*\)\n\([^\n]*\)/\2\1\4/'

或者,使用GNU sed减少括号数:

sed -r 's/(([^;]*;){'$((FIELD-1))'})([^;]*;)/\1\n\3\n/;h;s/[^\n]*\n([^\n]*).*/\1/;y/H1/X2/;G;s/([^\n]*)\n([^\n]*)\n([^\n]*)\n([^\n]*)/\2\1\4/'

示例:

$ FIELD=3
$ echo '"Hello World";"Number 1 is there";"tH1s-Has,1,HHunKnownData";' | sed -r 's/(([^;]*;){'$((FIELD-1))'})([^;]*;)/\1\n\3\n/;h;s/[^\n]*\n([^\n]*).*/\1/;y/H1/X2/;G;s/([^\n]*)\n([^\n]*)\n([^\n]*)\n([^\n]*)/\2\1\4/'
"Hello World";"Number 1 is there";"tX2s-Xas,2,XXunKnownData";

$ FIELD=2
$ echo '"Hello World";"Number 1 is there";"tH1s-Has,1,HHunKnownData";' | sed -r 's/(([^;]*;){'$((FIELD-1))'})([^;]*;)/\1\n\3\n/;h;s/[^\n]*\n([^\n]*).*/\1/;y/H1/X2/;G;s/([^\n]*)\n([^\n]*)\n([^\n]*)\n([^\n]*)/\2\1\4/'
"Hello World";"Number 2 is there";"tH1s-Has,1,HHunKnownData";

但可能有一种我没想到的简单方法。

答案 3 :(得分:0)

awk -F";" '{gsub("H","X",$3);gsub("1","2",$3);}1' Your_file

答案 4 :(得分:0)

这可能适合你(GNU sed):

sed 's/H/X/2g;s/1/2/2g' file

除了第一次出现H1X2之外,其他所有内容都会发生变化

如果是按;分隔的字段,请使用:

sed 's/H[^;]*;/&\n/;h;y/H/X/;H;g;s/\n.*\n//;s/1[^;]*;/&\n/;h;y/1/2/;H;g;s/\n.*\n//' file

这可以变异以适应许多值,所以:

echo -e "H=X\n1=2"|
sed -r 's|(.*)=(.*)|s/\1[^;]*;/\&\\n/;h;y/\1/\2/;H;g;s/\\n.*\\n//|' |
sed -f - file