当源包含 $ 时如何用 sed 替换

how to replace with sed when source contains $

我有一个文件包含:

$conf['minified_version'] = 100;

我想用 sed 增加 100,所以我有这个:

sed -r 's/(.*minified_version.*)([0-9]+)(.*)/echo "$((+1))"/ge'

问题在于,这会从原始文件中删除 $conf 以及任何缩进间距。我能够弄清楚的是,这是因为它试图 运行:

echo "    $conf['minified_version'] = $((100+1));"

所以它当然会尝试用一个没有值的变量替换 $conf

我建议的方法是在磁盘上创建一个文件,其中 只包含 minified_version 号码。然后,递增该数字将非常简单:

minified_version=$(< minified_version)
printf '%s\n' "$(( minified_version + 1 ))" >minified_version

...您可以在需要替换的源文件中放置一个印记。假设您有一个名为 foo.conf.in 的文件,其中包含:

$conf['minified_version'] = @MINIFIED_VERSION@

...那么您可以简单地 运行,在您的构建过程中:

sed -e "s/@MINIFIED_VERSION@/$(<minified_version)/g" <foo.conf.in >foo.conf

这样做的好处是您无需更改代码 foo.conf.in,因此您不必担心错误会覆盖文件的内容。这也意味着如果您将文件签入源代码管理,只要您只签入 foo.conf.in 而不是 foo.conf 就可以避免由于版本号更改附近的上下文而导致的潜在合并冲突。


现在,如果您确实想就地执行本机操作,这里有一个用纯本机编写的有点过度设计的方法bash(阅读infile 并写入 outfile;只要成功将 outfile 重命名回 infile 就地替换):

target='$conf['"'"'minified_version'"'"'] = '
suffix=';'
while IFS= read -r line; do
  if [[ $line = "$target"* ]]; then
    value=${line##*=}
    value=${value%$suffix}
    new_value=$(( value + 1 ))
    printf '%s\n' "${target}${new_value}${suffix}"
  else
    printf '%s\n' "$line"
  fi
done <infile >outfile

这是一个 awk 版本:

$ awk '/minified_version/{+=1} 1' file
$conf['minified_version'] = 101

这将查找包含 minified_version 的行。每当找到这样的一行时,第三个字段 将递增。