簡體   English   中英

BASH:測試參數是一個數字列表

[英]BASH: testing that arguments are a list of numbers

我試圖測試一個bash腳本的無數個參數( "$@" )是由空格分隔的數字( "#""#.#"".#""#." )(即# # # # ... )。 我試過了:

[ "$@" -eq "$@" ]

類似於我在這個答案中找到的,但我得到:

"[: too many arguments"

我也試過正則表達式,但似乎一旦正則表達式滿足,之后就會出現任何事情。 這是我的代碼:

if (($# >=1)) && [[ "$@" =~ ^-?[[:digit:]]*\.?[[:digit:]]+ ]]; then

它也需要不允許"#..""..#"

我不認為[ "$@" -eq "$@"]會以某種方式發揮作用。

像這樣的循環可以幫助讀取每個參數並檢測它是否是整數(bash不處理小數):

for i in $@;do
if [ "$i" -eq "$i" ] 2>/dev/null
then
    echo "$i is an integer !!"
else
    echo "ERROR: not an integer."
fi
done

在你的情況下,要確定參數是否是一個有效的整數/十進制數而不是所有那些正則表達式ifs,我們可以使用bash程序簡單地用自己的數字來划分數字。
如果是有效數字將返回1.00

所以在你的情況下這應該工作:

for i in $@;do
if [[ "$(bc <<< "scale=2; $i/$i")" == "1.00" ]] 2>/dev/null;then
    echo "$i is a number and thus is accepted"
else 
    echo "Argument $i not accepted"
fi
done

輸出:

root@debian:# ./bashtest.sh 1 3 5.3 0.31 23. .3 ..2 8..
1 is a number and thus is accepted
3 is a number and thus is accepted
5.3 is a number and thus is accepted
0.31 is a number and thus is accepted
23. is a number and thus is accepted
.3 is a number and thus is accepted
Argument ..2 not accepted
Argument 8.. not accepted

$@是一個字符串數組。 您可能希望一次處理一個字符串,而不是一起處理。

for i; do
    if [[ $i =~ ^-?[[:digit:]]+\.?[[:digit:]]*$ ]] || [[ $i =~ ^-?\.?[[:digit:]]+$ ]]; then
        echo yes - $i
    else
        echo no - $i
    fi
done

在bash中,模式匹配帶有乘法器語法,可以幫助您解決問題。 這是一個驗證所有參數的腳本:

for ARG ; do
    [[ "$ARG" = +([0-9]) ]] && echo "$ARG is integer number" && continue
    [[ "$ARG" = +([0-9]).*([0-9]) ]] && echo "$ARG is float number" && continue
    [[ "$ARG" = *([0-9]).+([0-9]) ]] && echo "$ARG is float number" && continue
    [[ "$ARG" = -+([0-9]) ]] && echo "$ARG is negative integer number" && continue
    [[ "$ARG" = -+([0-9]).*([0-9]) ]] && echo "$ARG is negative float number" && continue
    [[ "$ARG" = -*([0-9]).+([0-9]) ]] && echo "$ARG is negative float number" && continue
    echo "$ARG is not a number."
done

for循環自動使用腳本接收的參數來加載變量ARG。 來自循環的每個測試將變量的值與模式[0-9]乘以+或*(+為1或更大,*為零或更多)進行比較,有時彼此相鄰有多個模式。 以下是輸出的示例用法:

$ ./script.sh 123 -123 1.23 -12.3 1. -12. .12 -.12 . -. 1a a1 a 12345.6789 11..11 11.11.11 
123 is integer number
-123 is negative integer number
1.23 is float number
-12.3 is negative float number
1. is float number
-12. is negative float number
.12 is float number
-.12 is negative float number
. is not a number.
-. is not a number.
1a is not a number.
a1 is not a number.
a is not a number.
12345.6789 is float number
11..11 is not a number.
11.11.11 is not a number.

我將假設您的意思是十進制數,僅限於使用點表示小數點的國家/地區的整數或浮點數。 而這樣的國家不使用分組字符( 1,123,456.00125 )。

不包括:科學( 3e+4 ),十六進制( 0x22 ),八進制( \\033033 ),其他基數( 32#wer )或算術表達式( 2+2 9/7 9**3等)。

在這種情況下,數字應僅使用數字,一個(可選)符號和一個(可選)點。

這個正則表達式檢查上面的大部分內容:

regex='^([+-]?)([0]*)(([1-9][0-9]*([.][0-9]+)?)|([.][0-9]+))$'

用語言:

  • 可選符號( +-
  • 隨后是任意數量的可選零。
  • 其次是(... | ...... | ...)

    1. 數字[1-9]后跟零或更多數字[0-9] (可選),后跟一個點和數字。
    2. 沒有數字后跟一個點后跟一個或多個數字。

像這樣(因為你將問題標記為bash):

regex='^([+-]?)([0]*)(([1-9][0-9]*([.][0-9]+)?)|([.][0-9]+))$'
[[ $n =~ $regex ]] || { echo "A $n is invalid" >&2; }

這將接受0.0.0作為有效但不是0.也不是0

當然,這應該在循環中完成,如下所示:

regex='^([+-]?)([0]*)(([1-9][0-9]*([.][0-9]+)?)|([.][0-9]+))$'

for    n
do     m=${n//[^0-9.+-]}       # Only keep digits, dots and sign.
       [[ $n != "$m" ]] && 
           { echo "Incorrect characters in $n." >&2; continue; }
       [[ $m =~ $regex ]] || 
           { echo "A $n is invalid" >&2; continue; }
       printf '%s\n' "${BASH_REMATCH[1]}${BASH_REMATCH[3]}"
done

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM