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
?
答案 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:]]
再使用了一个捕获组,因此我不必为每个命令键入两次。[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