Sed

sed - 為什麼我必須雙重轉義特定字元?

  • August 3, 2022

這只是一個顯示問題的測試文件:

原始部分如下所示:

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 的讀取方式有什麼不同?
  • 為什麼必須雙重轉義左括號,而它與右括號完全可以正常工作而根本沒有轉義?

我只是想明白這一點。我現在知道該怎麼做,但我不滿足於不知道這個細節..

謝謝,克里斯

這是因為您沒有引用您的 sed 表達式(壞主意,養成將sed命令放在單引號中的習慣)。您需要轉義的原因[是因為[它在正則表達式中具有特殊含義,它打開一個字元類(例如[abc],將匹配ab或之一c)。您不需要轉義,]因為 sed 足夠聰明,可以知道在這種情況下,]不會關閉字元類,因為沒有[關閉前。

現在,因為您沒有引用 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 現在給出\[而不是[

如果您總是引用您的 sed 命令,所有這些問題都會消失:

$ sed 's/\[/:/g' jctl.log
arch systemd:908]:

引用自:https://unix.stackexchange.com/questions/712293