使用Sed命令替换包含特殊字符"&"的字符串

6

test.csv的内容如下:

XYZ,IN123

这是我的脚本:
Var1=IN123
Var2=A&B
sed -i "s/$Var1/$Var2/g" test.csv

这是我用来替换test.csv内容的简单代码,当代码发现IN123时,它将被替换为A&B。

所以预期输出结果为:

XYZ,A&B

但是使用以上代码我得到的结果是:
XYZ,AIN123B

我做错了什么?
4个回答

14

既然问题要求使用SED实现,关于它有一个不太知名但在这里非常有用的功能 - 定界符可以是任何你想要的字符,只要它们不在替换字符串中。

因此,对于上面的例子,你可以这样做:

sed -i "s|$Var1|$Var2|g" test.csv

..并且你可以用 $ 或 : 或任何你喜欢的其他字符代替它。


我希望我能给你+10,这对我帮助最大!现在sed看起来很干净、很好用!非常感谢你! - kamil_debski
但是... 如果我错了,这并不能在每个sed语句中起作用,比如:sed '/pattern/i line1' file.txt 但在修改后的版本中,它将无法工作:sed ':pattern:i line1' file.txt - kamil_debski
在MacOS上,它显示“sed:1:无效的命令代码f”。 - Binh Thien

7
很遗憾,你被 `sed` 替换字符串中的特殊字符 `&` 搞混了。这个元字符表示“所有匹配成功的模式”。为了得到一个字面上的 & 符号,你需要对其进行转义:
Var1='IN123'
Var2='A\&B'
sed -i "s/$Var1/$Var2/g" test.csv

单引号在赋值中是必需的,以防止\&被解释为转义序列。我为了对称性在两个变量中都加了它们。

1
嗨Tom,这是我发布的示例内容。实际上,我正在使用两个输入文件进行操作。第一个文件包含Var1、Var2,第二个文件是相同的test.csv。你是说在输入文件中,我必须处理这个吗?我需要用"&"替换"&"吗? - Programmer
@Java程序员,如果你想使用sed,那么是的。然而,考虑到你问题的全部细节,似乎有更好的替代方案可用。你应该编辑你的问题,展示你的文件样本和期望的输出。 - Tom Fenech
执行命令时,我遇到了以下错误:sed: 1: "test.csv": undefined label 'est.csv' - Boris
@Boris 我认为这可能是由于你的sed版本中-i开关的行为所致。https://dev59.com/IGct5IYBdhLWcg3wL6ui#69955786 尝试使用sed -i''或传递一个非空字符串以创建具有该后缀的备份文件。 - Tom Fenech
谢谢,sed -i'' 工作了! - Boris

4

如果你不想处理正则表达式和转义,可以使用以下awk命令:

Var1='IN123'
Var2='A&B'
awk -v v1="$Var1" -v v2="$Var2" 'BEGIN{FS=OFS=","} $2==v1{$2=v2} 1' test.csv
XYZ,A&B

你能详细说明一下吗?特别是整个awk语句。我知道-v可以将变量提供给BEGIN块,并且该块在赋值后执行。然后有FS和OFS(输出字段分隔符),但是这部分$2==v1{$2=v2} 1是什么意思? - harperville
$2==v1 checks if 2nd column equals to v1 and {$2=v2} sets 2nd column to v2 - anubhava
好的,我明白了。最后的 1 是什么意思? - harperville
1是用于打印数据。 - anubhava
我在 Linux 和 Mac 上检查过了,这个程序并没有像我希望的那样工作。也许自此帖以来 AWK 有些变化,有人能修复一下吗? - Farley
在我的OSX和Linux上,它运行得非常好,使用awk。 - anubhava

1

&是一个特殊字符,因此您需要使用\。需要以这种方式指定Var2。

Var2="A\&B"


嗨Vargan,这是我发布的示例内容。实际上,我是从两个输入文件中进行操作的。第一个文件包含Var1、Var2,而第二个文件是相同的test.csv。你是说我必须在输入文件本身中处理它吗?我需要用“&”替换“&”吗? - Programmer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接