[英]Why do quotes in shell scripts behave differently from quotes in shell commands?
[英]Why do sed a and sed s commands behave differently with respect to escape characters under single quotes and double quotes?
我知道sed
表達式中的單引號和雙引號之間存在差異,但我不知道sed a
和sed s
表達式之間存在差異。
對於sed s
表達式, \t
在單引號和雙引號中都被正確地翻譯為制表符。 \\t
在雙引號中也做同樣的事情。
# '\t' works for single quotes
$ echo -e "abc\n123" | sed 's|abc|&\n\tdef|'
abc
def
123
# '\\t' fails for single quotes
$ echo -e "abc\n123" | sed 's|abc|&\\n\\tdef|'
abc\n\tdef
123
# '\t' works for double quotes
$ echo -e "abc\n123" | sed "s|abc|&\n\tdef|"
abc
def
123
# '\\t' also works for double quotes
$ echo -e "abc\n123" | sed "s|abc|&\\n\\tdef|"
abc
def
123
但是,在sed a
表達式中,我必須在單引號表達式中使用\\t
並在帶有雙引號的表達式中使用\\\t
。
# '\t' fails for single quotes
$ echo -e "abc\n123" | sed '/abc/a\tdef'
abc
tdef
123
# '\\t' works for single quotes
$ echo -e "abc\n123" | sed '/abc/a\\tdef'
abc
def
123
# '\t' fails for double quotes
$ echo -e "abc\n123" | sed "/abc/a\tdef"
abc
tdef
123
# '\\t' fails for double quotes
$ echo -e "abc\n123" | sed "/abc/a\\tdef"
abc
tdef
123
# '\\\t' works for double quotes
$ echo -e "abc\n123" | sed "/abc/a\\\tdef"
abc
def
123
由於這種現象,我不得不將我的sed a
表達式更改為sed s
以統一輸出。 一切都很完美,但我想要一個解釋。
上面的命令在 Ubuntu 20.04 上執行。
sed
不知道您使用哪些引號。 shell 解析並刪除引號。 在單引號內,文本完全逐字保留; 在雙引號內,shell 執行變量替換、命令替換和反斜杠處理。 規則很簡單,但有時令人驚訝:簡而言之,反斜杠將下一個字符引用為文字,因此,一對反斜杠被轉換為單個反斜杠。 但是,保留不需要轉義的字符前面的反斜杠。 例如, \t
等價於雙引號內的\\t
。
sed
執行另一輪反斜杠處理。 在某些情況下,某些版本的sed
將\t
理解為表示文字制表符,但通常不在a
、 c
或i
命令之后的文本中。
這里的實際問題可能實際上是關於a
命令的格式。 這在sed
版本之間有所不同,但在 Ubuntu 上開箱即用,它只是在命令之后輸出文字文本。 在這種情況下,反斜杠只是一個文字反斜杠,它再次轉義下一個字符以確保它被按字面解釋。 與 shell 不同, sed
只是刪除了這個反斜杠。
在 Bash 中,您可以使用$'...'
“C-style” 字符串,它可以讓您對文字制表符進行符號編碼。 但是,您需要在幾個地方添加文字反斜杠: sed
不接受s
命令中未轉義的文字換行符,並且 a 后面a
制表符需要反斜杠,以免它作為無關緊要的空格被跳過。
printf '%s\n' abc 123 ghi |
sed -e $'s/abc/&\\\n\tdef/' \
-e $'/ghi/a\\\tjkl'
重申一下,在將字符串傳遞給命令(在本例中為sed
)之前,在$'...'
中, \t
被 shell 替換為文字制表符, \n
替換為換行符等。
在宏偉的計划中,您最好使用比sed
更隨意的工具。 awk 更容易閱讀、編寫和調試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.