如何在bash腳本中從命令行接受帶空格的輸入
目前我有一個 bash 腳本,我在其中接受來自命令行的輸入,但輸入帶有空格,並且 bash 腳本沒有讀取空格後面的單詞。腳本是這樣的
#!/bin/bash var1=$1 var2=$2 echo $var1 echo $var2
假設我將此文件保存為 test.sh。現在我的輸入是這樣的 -
./test.sh hi check1,hello world
輸出是 -
hi check1,hello
但我需要輸出為
hi check,hello world
PS:我不能用雙引號提供輸入,所以我需要一些其他的解決方案,我可以用空格讀取單詞
那是不可能的。參數的分詞發生在腳本執行之前,所以當它啟動時,參數已經被分詞了。閱讀有關“分詞”的
man bash
內容以了解有關詳細資訊的更多資訊。如果您知道將有 2 個參數,而第一個參數永遠不會包含空格,您可以通過某種方式解決它
#! /bin/bash first=$1 shift rest="$*" printf '<%s>\n' "$first" "$rest"
但它仍然會將多個空間縮小為一個。
正如@choroba 正確指出的那樣,您不能這樣做,至少不能開箱即用。
原因是:shell 在執行任何操作之前都會解析命令行,這是一個在幾個明確定義的步驟中發生的過程。其中一個步驟是“欄位拆分”,shell 將輸入行拆分為多個部分。考慮:
命令 arg1 arg2
不知何故,shell必須確定“command”是命令,“arg1”是第一個參數,“arg2”是第二個參數,不是嗎?為什麼“arg1”是第一個參數而不是“arg1 arg2”或者為什麼“command”是命令而不是“command arg1”等等,肯定是有原因的。
不,話雖如此,有兩件事會影響這種拆分的完成方式:(shell-)變數 IFS 和 OFS。IFS(“內部欄位分隔符”)是一個字元列表,如果未屏蔽,它將分隔欄位。在上面的範例中,“arg1”與“arg2”和“command”之間用空格隔開——這是 IFS 的一部分。
您可以自己將 IFS 設置為任何字元(甚至是空字元串),但預設情況下(在 POSIX 文件中說明)它設置為“空白”、“製表符”和“換行”。有關詳細資訊,請參閱了解 IFS。
在這個相當冗長的一般性介紹之後,這對您的問題意味著什麼?
- 您可以通過操作 IFS 來影響欄位拆分的完成方式,但您需要在腳本啟動之前執行此操作,即:
% SAVIFS="$IFS" ; 出口 IFS="" % /path/to/your/script arg1 arg2 ... % IFS="$SAVIFS"
- 您可以在腳本內並根據自己的規則進行欄位拆分。為此,您將所有參數擷取到一個字元串中並自己拆分:
#!/bin/bash chArgs="$*" arg1="" arg1="" [...] shopt -s lastpipe # 這里拆分$chArgs的內容,例如: 迴聲“$chArgs”| IFS=''讀取 arg1 arg2 printf "%s\n%s\n" "$arg1" "$arg2" # 或者,只是為了展示它是如何工作的: 迴聲“$chArgs”| IFS=',' 讀取 arg1 arg2 printf "%s\n%s\n" "$arg1" "$arg2"
但是請注意,在處理字元串時始終需要注意正確的引用 - 尤其是可能包含 IFS 字元的字元串。在您的範例中:
#!/bin/bash var1=$1 var2=$2 echo $var1 echo $var2
缺少這個正確的引用,我想這是一個(n 額外的)原因,它沒有像您預期的那樣工作。嘗試:
#!/bin/bash var1="$1" var2="$2" echo "$var1" echo "$var2"