Bash

為什麼sudo -i而不是sudo刪除換行符?

  • June 3, 2018

什麼可以解釋下面的例子,我該如何解決這個問題,最好不要大量引用雜技?我正在使用$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似乎沒有考慮到這一點。

無論如何,如果您將所需的命令儲存在一個文件中並將其作為腳本執行,那麼引用此類問題可能會變得相當容易。

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