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

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

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

A
B
C

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

sed -i '2s/^.*$/X/' a.txt

例如,将 更改B为。X

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

#!/bin/bash

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

head a.txt
sed -i '2s/^.*$/fname=\"$myaddress\"/' a.txt
head a.txt

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

fname="/home/"
A
B
C

A
fname="$myaddress"
C

我的问题是,我怎样才能sed真正打印价值存储在? 中myaddress并由$myaddress?引用

答案1

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

  • 分隔符本身(上面,您使用了/
  • &被匹配的字符串替换
  • 需要转义的换行符
  • \它用于逃避上述所有内容并介绍\1\2...

喜欢:

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

sed "s/regexp/$escaped_var/g"

由于这相当麻烦,您可能想使用perl

v=$var perl -pe 's/regexp/$ENV{v}/g'

sed的等价物2s是:

v=$var perl -pe 's/regexp/$ENV{v}/g if $. == 2'

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

v=$myaddress perl -pe '$_ = "fname=\"$ENV{v}\"\n" if $. == 2'

另一个优点是它也可以处理二进制数据,并且您可以使用一个-i选项进行就地编辑,而使用 时sed,您只能在sedGNU 的系统上执行此操作sed

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

答案2

shell 不解释单引号内的变量。您需要将它们更改为双引号。由于您的变量中有斜杠,因此您应该使用不同的分隔符:

sed -i "2s|^.*\$|fname=\"$myaddress\"|" a.txt

请注意,我转义了行尾$,因此 shell 不会解释它。在这种情况下不会,但您应该养成转义$要保留在双引号中的 s 的习惯。您还可以使用几对引号来做到这一点:

sed -i '2s|^.*$|fname="'"$myaddress"'"|' a.txt

答案3

有两个问题:首先,正如 Kevin 已经指出的,如果要由 shell 扩展 shell 变量,则需要将它们括在双引号中。其次,您的替换字符串包含/,因此您不能/同时用作 的分隔符sed。如果您知道某些字符(例如,)肯定不会出现在替换字符串中,则可以使用该字符作为sed分隔符,这样您就得到

sed -i '2s,^.*$,fname="'"$myaddress"'",' a.txt

相关内容