Shell
創建通用函式來提出問題並驗證答案是否為空
我正在創建一個可以解決很多問題的 shell 應用程序,並且我使用了
read -p "<my_question>" <myvar>
好幾次。問題是我還想驗證答案是否為空。所以,我想創建一個通用函式來詢問並驗證它是否為空。如果是這樣,遞歸呼叫函式本身,直到使用者提供一些東西。當我將變數名稱“固定”為“userdatabase”時,一切都非常好。遵循函式聲明和用法:ask() { read -p "$1" $2 if [[ -z $userdatabase ]]; then echo Empty is not allowed ask "$1" $2 else echo $userdatabase fi } ask "Provides the user database: " userdatabase
當然,我不想將“使用者數據庫”作為應用程序將提出的所有問題的變數名。所以,我注意到我需要一種“動態”變數。讓思考更動態一點,它變成:
ask() { read -p "$1" $2 if [[ -z $$var ]]; then echo Empty is not allowed ask "$1" $2 else echo $$var fi } ask "Provides the user database: " $var
但是當我使用該實用程序時,我會收到類似 SOMENUMBERvar 的資訊。顯然我沒有以正確的方式在 shell 中使用“動態變數”。
那麼,如何創建一個函式來接收問題語句和一個變數名,該變數名將由
read -p
命令中的變數填充?
從最簡單的情況開始。做一個函式:
f() { read -p "Type smthng: " $1 ; }
呼叫函式,分配變數*$p來保存它的輸入,然後 在函式退出後顯示輸入:*
f p ; echo $p
它提示,我鍵入“woof”,並
echo $p
輸出相同的內容:Type smthng: woof woof
檢查變數的一種方法是將該函式包裝在另一個函式中:
g() { unset $1 ; until f "$1" && eval [ \"\$"$1"\" ] ; do echo wrong ; done ; }
棘手的部分是 OP 希望將變數名稱分配為函式參數,為此我使用“邪惡”
eval
來解析。將變數名稱作為函式參數傳遞很少(或需要),但這顯示了一種方法。測試它:
g p ; echo $p
它提示,我點擊
Enter
,它輸出錯誤資訊;然後在第二個提示符下,我輸入“foo”:Type smthng: wrong Type smthng: foo foo
這部分 OP 程式碼不起作用:
if [[ -z $$var ]]; then
$$
是一個返回目前 PID的bash
變數:man bash | grep -A 28 "Special Parameters$" | sed -n '1,3p;28,$p' Special Parameters The shell treats several parameters specially. These parameters may only be referenced; assignment to them is not allowed. $ Expands to the process ID of the shell. In a () subshell, it expands to the process ID of the current shell, not the subshell.
ask() { # $1 ---> message to user # $2 ---> "VARIABLE NAME" in which read will store response case ${2-} in '' | *[!a-zA-Z0-9_]* | [0-9]* ) echo >&2 "Oops you've selected an invalid variable name: \`$2'" exit 1;; esac read -p "$1" "$2" eval " case \${$2:++} in '' ) echo >&2 'Empty response not allowed.' ask '$1' '$2';; * ) echo \"\${$2}\";; esac " } VarName=${1-'humpty_dumpty'} ask "Provide the user database: " "$VarName"