Scripting

讀取命令刪除雙倍空格,只保留一個

  • April 28, 2021

我編寫了一個腳本,在本地機器上收集應用程序日誌,然後從遠端機器上收集。

它具有oldlogsdate讀取我要收集的日誌日期的變數。

例如,如果我輸入Apr 23它可以正常工作,因為只有一個空格,但如果我輸入(和Apr 4之間的兩個空格)它將刪除一個空格。Apr``4

注意:這oldlogsdate也是在使用者的遠端機器上設置的.bash_profile,然後輸入的日期通過使用sed命令進行更改。

printf "\n";read -p "Which Date Logs you want to collect = " oldlogsdate
ssh -qt remote-user-name@xxx.xxx.xxx.xxx "sed -i "s/oldlogsdate=.*/oldlogsdate=\'\"$oldlogsdate\"\'/" ~/.bash_profile"

oldlogsdate="Apr 7"

現在為什麼我要使用它Apr 23,它是命令Apr 4的一部分。ls

有沒有辦法在讀取命令中保留雙空格,或者其他更好的方法?

在此處輸入圖像描述

讀取命令刪除雙倍空格並只保留一個

它沒有。該read命令本身將內部空格保持原樣(但是,除非您設置IFS為空,否則它將修剪前導和尾隨空格;如果您不使用,它也會破壞反斜杠-r)。

read myVar <<<'Apr  4'
echo "$myVar"  # will output: Apr  4

那就是由於沒有雙引號變數而失去空格的人:

myVar2='Apr  4'
echo $myVar2  # will mangle spaces, please always use "$myVar2" instead

不正確引用變數不僅會使腳本行為不端,而且還可能引入潛在的安全風險。

正確的命令是

ssh -qt remote-user-name@xxx.xxx.xxx.xxx "sed -i 's/oldlogsdate=.*/oldlogsdate=\"$oldlogsdate\"/' ~/.bash_profile"

但它不是通用的,也不安全,因為它沒有考慮到$oldlogsdate值可能不僅包含空格,還可能包含撇號、斜杠、反斜杠、美元符號和驚嘆號。

請注意您的ssh命令行,將sed命令發送到另一端的部分:

ssh ... "sed -i "s/oldlogsdate=.*/oldlogsdate=\'\"$oldlogsdate\"\'/" ~/.bash_profile"
       ^^^^^^^^^..................................................^^^^^^^^^^^^^^^^^^

這裡有兩個帶引號的字元串,標有^. 中間的其餘部分沒有被引用,其中包括變數擴展$oldlogsdate。由於它沒有被引用,因此它受到分的影響,並Apr 7成為兩個詞Aprand 7。另請參閱:何時需要雙引號?

現在,ssh它足夠聰明,可以將它們重新粘合在一起,但現在原始的空白量已經失去,它只是增加了一個空格。

這有點類似於 shell 如何忘記其中的原始空格echo並將單詞與單個空格粘合在一起:

$ echo hello  world
hello world

但請注意,對於 SSH,單級引號沒有幫助,因為 SSH 將命令行傳遞給遠端端的 shell 進行解釋,並且在該 shell 中,單詞之間的額外空格也會失去。

所以這仍然不起作用:

$ ssh localhost echo "hello  world"
hello world

(本地外殼刪除引號,並ssh獲取echohello world,並傳遞給遠端echo hello world,它的工作原理如上。)

我們實際上必須對兩端進行引用以保持字元串完整:

$ ssh localhost 'echo "hello  world"'
hello  world

其實用 etc. 來更恰當地顯示單詞中斷的地方會更好printf ":%s\n" hello world,但結果是相似的。

切換引號以使雙引號位於最外層,讓本地 shell 擴展變數,並將單引號留給遠端,這樣可以最大限度地減少它所做的擴展量。您仍然需要反斜杠轉義要發送到另一端的任何雙引號。

$ greeting="hello  world"
$ ssh localhost "echo '$greeting'"
hello  world

只要變數本身不包含單引號,這應該可以工作。如果是這樣,事情會變得更醜陋,請參閱:Escape a variable for use as content of another script

我認為@sasha 答案中的命令行看起來應該適用於您的情況。

另請參閱,例如這個問題:在 ssh 中引用 $ host $ FOO 和 ssh $ host “sudo su user -c $ FOO” 類型構造 手頭的問題還有一層處理,但答案似乎也適用於“更簡單”的情況*。*

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