我有一个问题sed
,我可以通过以下简单示例重新创建。
考虑以下输入文件(输入.txt):
C:\A\quick\brown\fox\ jumps over the lazy dog
C:\A\quick\brown\fox\ ran with the hounds
我想生成以下输出
C:\Animal\ jumps over the lazy dog
C:\Animal\ ran with the hounds
我尝试使用 sed 创建一个简单的 shell 脚本,但它没有执行所需的替换。这是我的脚本:
FROM_PATTERN="C:\A\quick\brown\fox\"
TO_PATTERN="C:\Animal\"
#FROM_PATTERN="C:\\A\\quick\\brown\\fox\\" # Escaping backslash does not help either
#TO_PATTERN="C:\\Animal\\" # Escaping backslash does not help either
sed 's/$FROM_PATTERN/$TO_PATTERN/g' input.txt
#sed 's/"$FROM_PATTERN"/"$TO_PATTERN"/g' input.txt # Quoting the pattern does not help either
我正在运行的bash
版本GNU bash, version 4.4.12(3)-release-(x86_64-unknown-cygwin)
答案1
\
很特别:
- 作为 shell 中的引用运算符,包括内部双引号,可用于转义自身、
"
、$
和`
do 行延续。 - 作为正则表达式运算符(用于转义和引入新运算符)
s
位于sed
. - 在命令的替换部分中
s
sed
,它可以转义&
、本身和换行符(或引入 C 风格的转义序列,例如\n
在某些sed
实现中)。
另请注意,shell 参数扩展不在单引号字符串内执行。
所以在这里,你想要:
\
在字符周围使用单引号而不是双引号- 对命令
\
的左侧和右侧进行转义s
- 在必须扩展变量的部分使用双引号。
from_regexp='C:\\A\\quick\\brown\\fox\\'
escaped_replacement='C:\\Animal\\'
sed "s/$from_regexp/$escaped_replacement/g" < your-file
或者,您可以使用perl
而不是sed
可以替换固定字符串的位置,而不必担心特殊字符,如果您这样做的话:
from='C:\A\quick\brown\fox\'
to='C:\Animal\'
FROM=$from TO=$to perl -pe 's/\Q$ENV{FROM}\E/$ENV{TO}/g' < your-file
也可以看看如何确保插入到“sed”替换中的字符串转义所有元字符处理任意字符串。
答案2
这是在 Linux 机器上运行的,不确定 cygwin 的行为是否与 linux 上的 bash 相同。
PC1:~> echo 'C:\A\quick\brown\fox\ jumps over the lazy dog' | sed -ne 's|\(C:\\A\).\+\\\+\(.\+\)|\1nimal\2|p'
C:\Animal jumps over the lazy dog
PC1:~> echo 'C:\A\quick\brown\fox\ ran with the hounds' | sed -ne 's|\(C:\\A\).\+\\\+\(.\+\)|\1nimal\2|p'
C:\Animal ran with the hounds
PC1:~>
所以我使用了组捕获,重复使用“A”,然后在其后附加“nimal”。为了让事情更清楚一些,我使用了“|”作为替代分隔符以避免过多的正斜杠。
希望能帮助到你。