当源包含$

时间:2015-07-01 00:31:45

标签: sed escaping echo

我有一个包含以下内容的文件:

$conf['minified_version'] = 100;

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

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

问题是这会从原始内容中剥离$conf以及任何缩进间距。我能够弄清楚的是,这是因为它试图运行:

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

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

2 个答案:

答案 0 :(得分:2)

这是一个awk版本:

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

这会查找包含minified_version的行。无论何时找到这样的行,第三个字段$3都会增加。

答案 1 :(得分:1)

我建议的方法是让磁盘上的文件包含 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