为什么sed只替换第一个字符?

时间:2015-12-24 20:31:39

标签: sed

$ echo lcdefghijklmnopqrstblvcxyz | tr [a-i] [1-9] | sed 's/j/10/' | sed 's/k/11/' | sed 's/l/12/' | sed 's/m/13/' | sed 's/n/14/' | sed 's/o/15/' | sed 's/p/16/' | sed 's/q/17/' | sed 's/r/18/' | sed 's/s/19/' | sed 's/t/20/' | sed 's/u/21/' | sed 's/v/22/' | sed 's/w/23/' | sed 's/x/24/' | sed 's/y/25/' | sed 's/z/26/'
1234567891011l13141516171819202l223242526

long命令旨在用1..26替换a..z。请注意,有3&#34; l&#34;回显字符串中的字符。为什么第一个正确转换为&#34; 12&#34;然而另外两个(结果11113和202l223)不是<?p?

我在运行Cygwin的Windows 7 PC(bash 4.3.33(1)-release(x86_64-unknown-cygwin))和运行终端(bash 3.2)的MacBook Pro上尝试了这个,并得到了相同的结果。我期望结果是1..26连接。这是一个更大的问题的一部分,我沦为这个测试用例。

3 个答案:

答案 0 :(得分:3)

您需要g标志才能重复替换:

$ echo lll | sed 's/l/12/'
12ll
$ echo lll | sed 's/l/12/'g
121212

如果没有g标记,则s会替换第一个实例,如man sed中所述。

此外,您可以将所有这些命令放在sed的单个调用中。你不需要所有这些管道:

sed 's/j/10/g;s/k/11/g;s/l/12/g...'

答案 1 :(得分:1)

多个sed命令(g切换)

下,您可以尝试以下内容:

c=1 o=
for i in {a..z};do
    o+="s/$i/$((c++))/g;"
  done
sed -e "$o" <<<'lcdefghijklmnopqrstblvcxyz'
1234567891011121314151617181920212223242526

fold -s <<< ${o//;/; }
s/a/1/g; s/b/2/g; s/c/3/g; s/d/4/g; s/e/5/g; s/f/6/g; s/g/7/g; s/h/8/g; 
s/i/9/g; s/j/10/g; s/k/11/g; s/l/12/g; s/m/13/g; s/n/14/g; s/o/15/g; s/p/16/g; 
s/q/17/g; s/r/18/g; s/s/19/g; s/t/20/g; s/u/21/g; s/v/22/g; s/w/23/g; s/x/24/g; 
s/y/25/g; s/z/26/g;

然后

sed -e '
  s/a/1/g; s/b/2/g; s/c/3/g; s/d/4/g; s/e/5/g; s/f/6/g; s/g/7/g; s/h/8/g;
  s/i/9/g; s/j/10/g; s/k/11/g; s/l/12/g; s/m/13/g; s/n/14/g; s/o/15/g; s/p/16/g;
  s/q/17/g; s/r/18/g; s/s/19/g; s/t/20/g; s/u/21/g; s/v/22/g; s/w/23/g; s/x/24/g;
  s/y/25/g; s/z/26/g;
' <<<'lcdefghijklmnopqrstblvcxyz'
1234567891011121314151617181920212223242526

答案 2 :(得分:1)

这可能适合你(GNU sed):

sed -r '1{x;s/^/a1b2c3d4e5f6g7h8i9j10k11l12m13n14o15p16q17r18s19t20u21v22w23x24y25z26/;x};G;:a;s/([a-z])(.*\n.*\1([0-9]+))/\3\2/;ta;P;d' file

这使用lookup table来翻译所需的字符串。