2016-08-15 70 views
1
cat 1.txt | sed -E 's,game([0-9]+),game$(printf %03d \1),g' 

game001从替代1.txt更换的Game1与SED嵌套命令

game1 xxx vs yyy 
game11 aaa vs bbb 

到:

game001 xxx vs yyy 
game011 aaa vs bbb 

但结果是:

$ echo "game1 xxx vs yyy" | sed -E 's,game([0-9]+),game$(printf %03d \1),g' 
game$(printf %03d 1) xxx vs yyy 

如何使printf %03d \1更正如何评估?

回答

1

您需要使用双引号,当你需要代换

sed -E "s,game([0-9]+),game$(printf %03d \1),g" 1.txt 

编辑:

而且,我不认为sed可以传递的\1值外部命令。 perl可以在这种情况下帮助:

$ cat 1.txt 
game1 xxx vs yyy 
game11 aaa vs bbb 
game21 aaa vs bbb 

$ sed -E "s,game([0-9]+),game$(printf %03d \1),g" 1.txt 
game001 xxx vs yyy 
game001 aaa vs bbb 
game001 aaa vs bbb 

$ # can also use: perl -pe 's/game\K\d+/sprintf "%03d", $&/ge' 
$ perl -pe 's/game([0-9]+)/sprintf "game%03d", $1/ge' 1.txt 
game001 xxx vs yyy 
game011 aaa vs bbb 
game021 aaa vs bbb 
+0

perl的工作就像一个魅力! – pengguang001

0

不能同时使用shell命令和sed反向引用像这样(如果你能,你就必须双引号sed命令,看其他的答案)。 shell会在sed看到它之前尝试评估命令,但\1对shell没有任何意义。

你可以做到这一点如下,虽然:

$ sed -E 's/^(game)([[:digit:]]+)/\100\2/;s/^(game).{0,2}([[:digit:]]{3})/\1\2/' 1.txt 
game001 xxx vs yyy 
game011 aaa vs bbb 

第一次换人,s/^(game)([[:digit:]]+)/\100\2/,增加了在数字前面两个零game后:

$ sed -E 's/game([[:digit:]]+)/game00\1/' 1.txt 
game001 xxx vs yyy 
game0011 aaa vs bbb 

第二个替代,s/^(game).{0,2}([[:digit:]]{3})/\1\2/移除了在game和后面的三个数字之间最多有两个字符,以消除不需要的额外零。

注意

  • 我用/,而不是作为,分隔符,只是因为我更习惯了。
  • 我在^的行首开始加注game
  • 我为game使用了一个捕获组,因此我不必每个命令输入两次。
  • 我已经使用了POSIX字符类[[:digit:]]而不是[0-9]
  • 我用sed '<command>' 1.txt而不是cat 1.txt | sed '<command>'来避免useless use of cat
+0

感谢您与sed的解决方案! – pengguang001

0

只需使用AWK:

$ awk '{sub(/game/,""); $1=sprintf("game%03d",$1)} 1' file 
game001 xxx vs yyy 
game011 aaa vs bbb 

或一般要保存捕捉组与GNU AWK操作上的第三个参数匹配():

$ awk 'match($0,/(game)([0-9]+)(.*)/,a){ printf "%s%03d%s\n", a[1], a[2], a[3] }' file 
game001 xxx vs yyy 
game011 aaa vs bbb 

使用sed你会需要:

$ sed -E 's/(game)([0-9]) /\10\2 /; s/(game)([0-9]{2}) /\10\2 /' file 
game001 xxx vs yyy 
game011 aaa vs bbb