在 sed 中使用对 bash 字符串变量的引用

And*_*rew 2 sed shell-script quoting

我是一个相对的 Linux 新手。假设我有一个a.txt包含以下文本的文本文件:

A
B
C
Run Code Online (Sandbox Code Playgroud)

现在,如果我想更改第 2 行(包含B)上的文本,我可以使用以下sed命令:

sed -i '2s/^.*$/X/' a.txt
Run Code Online (Sandbox Code Playgroud)

改变BX,例如。

但现在假设我想编写一个sed命令,将第 2 行的文本更改为包含bash 字符串变量的内容。我想将第 2 行的文本更改为fname="myaddress",其中显式包含引号,并且 wheremyaddressbash 字符串变量(在其他地方定义)。为了尝试这样做,我创建了一个名为 bash shell 脚本mytest.sh并包含以下内容:

#!/bin/bash

myaddress="/home/"
echo fname=\"$myaddress\"

head a.txt
sed -i '2s/^.*$/fname=\"$myaddress\"/' a.txt
head a.txt
Run Code Online (Sandbox Code Playgroud)

现在,echo fname=\"$myaddress\"prints fname="/home/",这是我想要a.txt. 但是,sed打印fname="$myaddress"到第 2 行a.txt,可能是因为它在周围的撇号内。换句话说,上面的 bash shell 脚本的输出是:

fname="/home/"
A
B
C

A
fname="$myaddress"
C
Run Code Online (Sandbox Code Playgroud)

我的问题是,如何才能sed实际打印存储在 中并由其引用的myaddress$myaddress

Sté*_*las 5

如果您希望替换工作无论变量的内容是什么,您都必须转义变量中s命令右侧的特殊字符,sed其中:

  • 分隔符本身(上面,你用过/
  • & 由匹配的字符串替换
  • 需要转义的换行符
  • \用于逃避上述所有内容并引入\1\2...

喜欢:

escaped_var=$(printf '%s\n' "$var" | sed 's:[/&\]:\\&:g;s/$/\\/')
escaped_var=${escaped_var%?}

sed "s/regexp/$escaped_var/g"
Run Code Online (Sandbox Code Playgroud)

由于这很麻烦,您可能想perl改用:

v=$var perl -pe 's/regexp/$ENV{v}/g'
Run Code Online (Sandbox Code Playgroud)

相当于sed's2s将是:

v=$var perl -pe 's/regexp/$ENV{v}/g if $. == 2'
Run Code Online (Sandbox Code Playgroud)

当然,在您的情况下,您宁愿这样写:

v=$myaddress perl -pe '$_ = "fname=\"$ENV{v}\"\n" if $. == 2'
Run Code Online (Sandbox Code Playgroud)

另一个优点是它也适用于二进制数据,您可以使用一个-i选项进行就地编辑,而使用sed,您只能sed在 GNU 的系统上这样做sed

另请注意,NUL 字符不能存储在环境变量中。