Shell

創建通用函式來提出問題並驗證答案是否為空

  • March 15, 2017

我正在創建一個可以解決很多問題的 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"

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