用sed嵌套命令

时间:2016-08-15 02:24:59

标签: sed

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

替换1.txt

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

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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
  • 我已经为[[:digit:]]再使用了一个捕获组,因此我不必为每个命令键入两次。
  • 我使用了POSIX字符类[0-9]而不是sed '<command>' 1.txt
  • 我已使用cat 1.txt | sed '<command>'代替{{1}}来避免useless use of cat

答案 2 :(得分:0)

只需使用awk:

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

或者通常使用GNU awk对保存的捕获组进行操作以使第3个arg匹配():

$ 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