Bash
bash 腳本和互動式 shell 之間的空格差異
請告知為什麼會發生這種情況。
來自 Linux bash shell:
ps PID TTY TIME CMD 20406 pts/0 00:00:01 bash 26896 pts/0 00:00:00 ps
我執行以下
str="a b c d" printf "%s\n" ` echo $str ` a b c d
但來自 bash 腳本
#!/bin/bash . . . . str="a b c d" printf "%s\n" ` echo $str `
它列印:
a b c d
而腳本的預期結果應該是這樣的:
a b c d
我的 bash 腳本中缺少什麼?也許是 bash ENV,或者類似的東西?
我還
shopt
從我的 bash 腳本執行命令,結果如下:utocd off cdable_vars off cdspell off checkhash off checkjobs off checkwinsize off cmdhist on compat31 off compat32 off compat40 off compat41 off direxpand off dirspell off dotglob off execfail off expand_aliases off extdebug off extglob off extquote on failglob off force_fignore on globstar off gnu_errfmt off histappend off histreedit off histverify off hostcomplete on huponexit off interactive_comments on lastpipe off lithist off login_shell off mailwarn off no_empty_cmd_completion off nocaseglob off nocasematch off nullglob off progcomp on promptvars on restricted_shell off shift_verbose off sourcepath on xpg_echo off
我只能在兩種情況下重現此行為:
- 雙引號命令替換:
#!/bin/bash str="a b c d" printf "%s\n" "`echo $str`"
- 或更改內部欄位分隔符(
IFS
變數),例如:#!/bin/bash IFS=, str="a b c d" printf "%s\n" `echo $str`
在這兩種情況下,輸出都是
$ ./test.sh a b c d
要修復第一種情況,只需刪除引號,並恢復
IFS
只需將其設置為高於命令替換的預設值。IFS=$' \t\n'
稍微解釋一下為什麼在
IFS
更改時輸出會有所不同,它與雙引號有什麼共同點?讓我們從頭開始:
printf "%s\n" a b c d
明顯不同於
printf "%s\n" 'a b c d'
在第一種情況下,我們有四個單獨的單詞,並
printf
一個接一個地輸出它們,並為它們添加新行。在第二種情況下,整個a b c d
被視為一個單詞,並printf
直接將其輸出到終端。現在應該很明顯,echo $str
當附加雙引號時,輸出被視為單個單詞。現在是
IFS
開始發揮作用的地方。也就是說, tt 用於在擴展後拆分單詞,因此預設情況下IFS=$' \t\n'
表達式echo a b c d
輸出a b c d
,但IFS=,
它變成'a b c d'
了 - 一個單一的世界,儘管沒有明確使用引號。沒有變數可以更清楚地檢查:$ IFS=, $ printf "%s\n" `echo a b c d` a b c d $ IFS=$' \t\n' $ printf "%s\n" `echo a b c d` a b c d
最後一點:最好使用一種
$()
命令替換形式,而不是反引號,但這是不同的主題。