Bash為什麼
為什麼sudo -i
而不是sudo
刪除換行符?
什麼可以解釋下面的例子,我該如何解決這個問題,最好不要大量引用雜技?我正在使用
$n
來模擬多行命令字元串,以防它分散您對真正問題的注意力。~$ n=$'\n'; sudo -i echo "line1${n}line2${n}" line1line2 ~$
但
~$ n=$'\n'; sudo echo "line1${n}line2${n}" line1 line2 ~$
在 strace 下執行
sudo -i echo $'line1\nline2'
顯示 Bash 是這樣啟動的:9183 execve("/bin/bash", ["-bash", "--login", "-c", "echo line1\\\nline2\\\n"], ...
現在,
strace
在顯示字元串時顯示帶有反斜杠轉義的特殊字元,所以 Bash 實際上作為參數得到的-c
是,對於 shell,行尾的反斜杠標記續行並刪除反斜杠和以下換行符.echo line1*[backslash][newline]*line2*[backslash][newline]*
沒有
-i
,直接sudo
執行echo
,不經過外殼:9189 execve("/bin/echo", ["echo", "line1\nline2\n"], ...
在這裡,這是一個字面的換行符
echo
,並echo
適當地列印出來。這裡的想法必須是
sudo
嘗試添加一層外殼轉義以適應sh -c
採用單個字元串的事實,而sudo
它本身將命令作為不同的參數。比較以下情況:
sudo
轉義空格(這只是命令的名稱,沒有參數!):$ sudo -i 'echo foo' -bash: echo foo: command not found
sudo
轉義反斜杠,因此這實際上有效(Bashecho
不處理反斜杠):$ sudo -i echo 'foo\bar' foo\bar
與選項卡相同:
$ sudo -i echo $'foo\tbar' foo bar
在這裡,反斜杠上沒有額外的引號,因此 Bash 在處理 shell 命令行時將其刪除(
b
不是 shell 的特殊字元,不需要引號。這與 基本相同bash -c 'echo foo"b"ar'
):$ bash -c 'echo foo\bar' foobar
問題只是你不能用反斜杠轉義換行符,而且
sudo
似乎沒有考慮到這一點。無論如何,如果您將所需的命令儲存在一個文件中並將其作為腳本執行,那麼引用此類問題可能會變得相當容易。