Bash

如何在bash腳本中從命令行接受帶空格的輸入

  • January 7, 2022

目前我有一個 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

在這個相當冗長的一般性介紹之後,這對您的問題意味著什麼?

  1. 您可以通過操作 IFS 來影響欄位拆分的完成方式,但您需要在腳本啟動之前執行此操作,即:
% SAVIFS="$IFS" ; 出口 IFS=""
% /path/to/your/script arg1 arg2 ...
% IFS="$SAVIFS"
  1. 您可以在腳本內並根據自己的規則進行欄位拆分。為此,您將所有參數擷取到一個字元串中並自己拆分:
#!/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"

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