这只是一个显示问题的测试文件。原来的部分看起来像这样:
arch systemd[908]:
现在我可以用“:”字符替换右括号
krys@archeos:~/test]$ cat jctl.log | cut -d " " -f 4,5 | head | sed s/]/:/g
arch systemd[908::
当我尝试更换开口支架时,它不起作用:
krys@archeos:~/test]$ cat jctl.log | cut -d " " -f 4,5 | head | sed s/[/:/g
sed: -e expression #1, char 7: unterminated `s' command
然后我用 1 \ 字符转义了“[”,但它仍然不起作用
krys@archeos:~/test]$ cat jctl.log | cut -d " " -f 4,5 | head | sed s/[/:/g
sed: -e expression #1, char 7: unterminated `s' command
使用 2 个“\”即可:
krys@archeos:~/test]$ cat jctl.log | cut -d " " -f 4,5 | head | sed s/\\[/:/g
arch systemd:908]:
这是我的问题:
- 为什么它适用于右括号但不适用于左括号? sed 或 bash 读取此内容的方式有何不同?
- 为什么有必要双重转义左括号,而它与右括号一起工作得很好,根本不需要转义它?
我只是想了解这一点。我现在知道如何做到这一点,但我对不知道细节感到不满意。
答案1
sed
这是因为您没有引用 sed 表达式(坏主意,养成将命令放在单引号中的习惯)。您需要转义的原因[
是因为[
它在正则表达式中具有特殊含义,它打开一个字符类(例如,将匹配、或[abc]
之一)。您不需要转义,因为 sed 足够聪明,知道在这种情况下,不会关闭字符类,因为没有前面可以关闭。a
b
c
]
]
[
现在,因为您没有引用 sed 表达式,这意味着 shell 将尝试解释它前将其传递给sed
.因此,shell 会看到您的\[
,并消耗转义符以将其未转义的传递给 sed。您可以通过以下方式查看此操作的实际效果set -x
:
$ set -x
$ sed s/\[/:/g jctl.log
+ sed 's/[/:/g' jctl.log
sed: -e expression #1, char 7: unterminated `s' command
正如您所看到的,实际运行的命令是sed 's/[/:/g' jctl.log
而不是sed 's/\[/:/g' jctl.log
:shell 已经消耗了转义符。然后会失败,因为 sed 正在寻找结束符]
,但没有找到,因此将整个字符串/:/g
视为字符类的内容,因此失败,因为它找不到命令的结尾s///
。
添加第二级转义允许 shell 消耗一级转义,然后仍然将转义传递[
给 sed:
$ sed s/\\[/:/g jctl.log
+ sed 's/\[/:/g' jctl.log
arch systemd:908]:
您可以在上面的输出中看到 sed 是\[
now 给出的,而不是[
。
如果您始终引用 sed 命令,所有这些问题都会消失:
$ sed 's/\[/:/g' jctl.log
arch systemd:908]: