Vil*_*age 1 bash replace symbols sed
我正在尝试使用sed和BASH变量进行查找和替换.由于替换的内容包含许多/字符,我使用的#代替/,通常用于sed:
sed -i "0,\#^$word#s##$replacement#" ./file
Run Code Online (Sandbox Code Playgroud)
我要替换的项目包含\符号:
replacement=$(echo "\macro{30\percent of bears eat fish.}")
Run Code Online (Sandbox Code Playgroud)
但是,当我进行更换时,\总会消失.
"\macro{30\percent of bears eat fish.}"\t出现,它被解释为缩进,但我只是希望它\t在输出中打印.我怎样才能做一个查找和替换为sed的时候\,/或其他符号可能替换文本中找到?
当你拥有shell并且sed都试图解释反斜杠时,生活总是变得棘手.事实上,它真的很痛苦.
我们来看一个简单的例子:你想sed用一个符号替换一行上的第一个反斜杠:
sed 's/\\/@/' file
Run Code Online (Sandbox Code Playgroud)
请注意,我们需要在这里指定两个反斜杠,并且因为命令是单引号,所以shell没有为我们做任何解释 - 谢天谢地!
现在,让我们假设我们需要使用双引号而不是单引号.现在我们需要输入:
sed "s/\\\\/@/" file
Run Code Online (Sandbox Code Playgroud)
为什么?因为shell首先扫描字符串,并且它看到反斜杠反斜杠并将其转换为单个反斜杠; 然后它会看到第二个反斜杠反斜杠并将其转换为另一个反斜杠.那么,然后sed看到两个反斜杠并做你想做的事情.
你可能/bin/echo在你的机器上(我在我的机器上,Mac OS X 10.7.3)有一个bash与内置机器不同的机器echo.我可以得到以下输出(来自/bin/bash):
$ echo '\\' | sed "s/\\\\/@/"
@\
$ /bin/echo '\\' | sed "s/\\\\/@/"
@\
$ echo '\\' | sed 's/\\\\/@/'
@
$ /bin/echo '\\' | sed 's/\\\\/@/'
@
$
Run Code Online (Sandbox Code Playgroud)
让我们在工作中抛出另一个扳手(我的大脑受伤了 - 你的应对怎么样?).我得到了一个不同的答案/bin/sh(这是非常相似但不完全相同/bin/bash;磁盘上的差异是64字节,两者都是bash版本3.2):
$ echo '\\' | sed "s/\\\\/@/"
@
$ /bin/echo '\\' | sed "s/\\\\/@/"
@\
$ echo '\\' | sed 's/\\\\/@/'
\
$ /bin/echo '\\' | sed 's/\\\\/@/'
@
$
Run Code Online (Sandbox Code Playgroud)
是的,有区别.而现在我很困惑!
在您的讨论中,您提到使用:
replacement=$(echo "\\\macro{some text}")
Run Code Online (Sandbox Code Playgroud)
这使生活变得复杂.你有shell处理文本,而bash的内置echo也处理文本.如果你使用,bash当sh你得到一个答案,如果你使用,bash因为bash你得到另一个答案.
当我用bashas 测试时sh,我发现:
replacement="\\\\macro{some text}" # 4 slashes, not 3
Run Code Online (Sandbox Code Playgroud)
这会得到两个反斜杠$replacement.你可以通过运行来证明:
$ /bin/echo "$replacement"
\\macro{some text}
$ echo "$replacement"
\macro{some text}
$
Run Code Online (Sandbox Code Playgroud)
非常有用......所以,为了让$(echo ...)你在随后的输出中产生两个反斜杠echo,你需要在字符串中不少于16个(!)反斜杠:
$ replacement=$(echo "\\\\\\\\\\\\\\\\macro{some text}")
$ echo "$replacement"
\\macro{some text}
$
Run Code Online (Sandbox Code Playgroud)
注意:这适用于bash-as-sh; 运行bash-as-bash,你得到:
$ replacement=$(echo "\\\\\\\\\\\\\\\\macro{some text}")
$ echo "$replacement"
\\\\\\\\macro{some text
$
Run Code Online (Sandbox Code Playgroud)
生活不是很有趣!因此,要使其工作,您将不得不对搜索模式和替换模式进行预处理,以便在每个模式中获得足够的反斜杠.多少?啊...
这是一个我称之为测试脚本,具有令人惊叹的原创性和明确的名称,xx:
#!/bin/bash
echo "happy /word/ today" > file
word="/word/"
/bin/echo "word=<<$word>>"
replacement='\\\\macro{some text}'
/bin/echo "repl=<<$replacement>>"
echo "repl=<<$replacement>>"
/bin/echo sed -e "s#$word#$replacement#" file
sed -e "s#$word#$replacement#" file
echo
replacement="\\\\macro{some text}"
/bin/echo "repl=<<$replacement>>"
echo "repl=<<$replacement>>"
/bin/echo sed -e "s#$word#$replacement#" file
sed -e "s#$word#$replacement#" file
echo
replacement=$(echo "\\\\\\\\macro{some text}")
/bin/echo "$replacement"
echo "$replacement"
echo
replacement=$(echo "\\\\\\\\\\\\\\\\macro{some text}")
/bin/echo "$replacement"
echo "$replacement"
Run Code Online (Sandbox Code Playgroud)
这是从bash xx以下输出:
$ bash xx
word=<</word/>>
repl=<<\\\\macro{some text}>>
repl=<<\\\\macro{some text}>>
sed -e s#/word/#\\\\macro{some text}# file
happy \\macro{some text} today
repl=<<\\macro{some text}>>
repl=<<\\macro{some text}>>
sed -e s#/word/#\\macro{some text}# file
happy \macro{some text} today
\\\\macro{some text}
\\\\macro{some text}
\\\\\\\\macro{some text}
\\\\\\\\macro{some text}
$
Run Code Online (Sandbox Code Playgroud)
这是来自的输出sh xx:
$ sh xx
word=<</word/>>
repl=<<\\\\macro{some text}>>
repl=<<\\macro{some text}>>
sed -e s#/word/#\\\\macro{some text}# file
happy \\macro{some text} today
repl=<<\\macro{some text}>>
repl=<<\macro{some text}>>
sed -e s#/word/#\\macro{some text}# file
happy \macro{some text} today
\\macro{some text}
\macro{some text}
\\\\macro{some text}
\\macro{some text}
$
Run Code Online (Sandbox Code Playgroud)
在所有这些(大部分)问题的答案中.要说我很惊讶地发现bash-as-bash和bash-as-sh之间的这种差异并没有开始覆盖领土.