Sed 查找和替换表达式适用于文字但不适用于变量插值

Sed find and replace expression works with literal but not with variable interpolation

对于以下 MVCE:

echo "test_num: 0" > test.txt
test_num=$(grep 'test_num:' test.txt  | cut -d ':' -f 2)
new_test_num=$((test_num + 1))

echo $test_num
echo $new_test_num

sed -i "s/test_num: $test_num/test_num: $new_test_num/g" test.txt
cat test.txt

echo "sed -i "s/test_num: $test_num/test_num: $new_test_num/g" test.txt"

sed -i "s/test_num: 0/test_num: 1/g" test.txt
cat test.txt

输出

0 # parsed original number correctly
1 # increment the number
test_num: 0 # sed with interpolated variable, does not work
sed -i s/test_num: 0/test_num: 1/g test.txt # interpolated parameter looks right
test_num: 1 # ???

为什么 sed -i "s/test_num: $test_num/test_num: $new_test_num/g" test.txt 没有产生预期的结果,而 sed -i "s/test_num: 0/test_num: 1/g" test.txt 在上面的例子中工作得很好?

如评论中所述,${test_num}中有一个白色的space。因此,在您的 sed 中,冒号和变量之间不应有空 space。

此外,我想您应该用花括号 {} 将变量括起来以提高可读性。

sed "s/test_num:${test_num}/test_num: ${new_test_num}/g" test.txt 
test_num: 1

如果您只想要 ${test_num} 中的数字,您可以尝试这样的操作:

grep 'test_num:' test.txt | awk -F ': ' '{print }'

awk 允许指定多于 1 个字符的分隔符。

除了grep|cut你还可以使用sed.

#! /bin/bash

exec <<EOF
test_num: 0
EOF

grep 'test_num:' | cut -d ':' -f 2

exec <<EOF
test_num: 0
EOF

sed -n 's/^test_num: //p'

sed 中使用正则表达式替换时 $ 有特殊含义。

建议重建您的 sed 命令段如下:

sed -i 's/test_num: '$test_num'/test_num: '$new_test_num'/g' test.txt

其他选项,使用echo命令扩展sed命令中的变量。

sed_command=$(echo "s/test_num:${test_num}/test_num: ${new_test_num}/g")
sed -i "$sed_command" test.txt