用 Bash 变量替换 sed

Posted

技术标签:

【中文标题】用 Bash 变量替换 sed【英文标题】:sed substitution with Bash variables 【发布时间】:2011-12-02 14:09:38 【问题描述】:

我正在尝试使用 Bash 脚本中的 sed 更改文本文件中的值,

sed 's/draw($prev_number;n_)/draw($number;n_)/g' file.txt > tmp

这将在for 循环中。为什么它不起作用?

【问题讨论】:

【参考方案1】:

' 中的变量不会在 Bash 中被替换。要获得字符串替换(或插值,如果您熟悉 Perl),您需要将其更改为使用双引号 " 而不是单引号:

# Enclose the entire expression in double quotes
$ sed "s/draw($prev_number;n_)/draw($number;n_)/g" file.txt > tmp

# Or, concatenate strings with only variables inside double quotes
# This would restrict expansion to the relevant portion
# and prevent accidental expansion for !, backticks, etc.
$ sed 's/draw('"$prev_number"';n_)/draw('"$number"';n_)/g' file.txt > tmp

# A variable cannot contain arbitrary characters
# See link in the further reading section for details
$ a='foo
bar'
$ echo 'baz' | sed 's/baz/'"$a"'/g'
sed: -e expression #1, char 9: unterminated `s' command

进一步阅读:

Difference between single and double quotes in Bash Is it possible to escape regex metacharacters reliably with sed Using different delimiters for sed substitute command 除非您需要在其他文件中使用它,否则您可以使用-i flag to change the file in place

【讨论】:

也许还提到如果变量包含斜杠,您需要使用字符串中不出现的不同分隔符(或反斜杠转义每次出现的分隔符)。斜线是s 的常见默认值,但您可以使用任何标点符号; sed "s%draw($prev_number;n_)%draw($number;n_)%g" file.txts#from#to#gs_from_to_g 如果变量包含换行符(“\n”)则不起作用 但它确实曾经逃脱(对于我的用例)也有斜线:changelogEscaped=$(sed -e 's%\/%\\/%g; $!a\'$'\n''\\n' <<<"$changelog" | tr -d '\n') 感谢上面的链接。【参考方案2】:

单引号内的变量不展开,但在双引号内展开。在这种情况下使用双引号。

sed "s/draw($prev_number;n_)/draw($number;n_)/g" file.txt > tmp

你也可以让它与eval一起工作,但不要那样做!!

【讨论】:

感谢工作。您介意解释一下您所说的扩展是什么意思吗?我的直觉告诉我,它应该类似于变量替换。还有为什么不使用 eval?【参考方案3】:

这可能会有所帮助:

sed "s/draw($prev_number;n_)/draw($number;n_)/g" 

【讨论】:

【参考方案4】:

您可以使用如下变量。就像这里一样,我想替换hostname,即文件中的系统变量。我正在寻找字符串 look.me 并将整行替换为 look.me=<system_name>

sed -i "s/.*look.me.*/look.me=`hostname`/"

您还可以将系统值存储在另一个变量中,并可以使用该变量进行替换。

host_var=`主机名`

sed -i "s/.*look.me.*/look.me=$host_var/"


输入文件:

look.me=demonic

文件的输出(假设我的系统名称是prod-cfm-frontend-1-usa-central-1):

look.me=prod-cfm-frontend-1-usa-central-1

【讨论】:

【参考方案5】:

我需要在 github 操作中输入我发布的 github 标签。这样在发布时它会自动打包并将代码推送到工件。

这就是我的做法。 :)

  - name: Invoke build
    run: |
      # Gets the Tag number from the release
      TAGNUMBER=$(echo $GITHUB_REF | cut -d / -f 3)
      
      # Setups a string to be used by sed
      FINDANDREPLACE='s/$GITHUBACTIONSTAG/'$(echo $TAGNUMBER)/
      
      # Updates the setup.cfg file within version number
      sed -i $FINDANDREPLACE setup.cfg
      
      # Installs prerequisites and pushes 
      pip install -r requirements-dev.txt
      invoke build

回想起来,我希望我在 python 中通过测试做到这一点。然而,做一些 bash 很有趣。

【讨论】:

以上是关于用 Bash 变量替换 sed的主要内容,如果未能解决你的问题,请参考以下文章

bash shell参数展开(Shell Parameter Expansion):替换变量(variable)中的字符串

Sed用shell变量替换[重复]

Sed 删除匹配行,匹配的字符用Shell变量替换,且变量里含有斜杠“/”时,无法删除

如何在sed中使用变量

sed调用shell变量及替换包含关键字的整行

如何使用 sed 或 awk 命令用变量(变量保存 Unix 脚本)查找和替换文本