web-dev-qa-db-ja.com

変数がBashの数値かどうかをどうやってテストするのですか?

スクリプトに渡された引数が数値かどうかを確認するにはどうすればよいかわかりません。

私がやりたいのはこのようなことです。

test *isnumber* $1 && VAR=$1 || echo "need a number"

何か手助け?

505
Flávio Amieiro

1つの方法は、次のように正規表現を使うことです。

re='^[0-9]+$'
if ! [[ $yournumber =~ $re ]] ; then
   echo "error: Not a number" >&2; exit 1
fi

値が必ずしも整数ではない場合は、正規表現を適切に修正することを検討してください。例えば:

^[0-9]+([.][0-9]+)?$

...または、符号付きの数字を処理するには

^[+-]?[0-9]+([.][0-9]+)?$
675
Charles Duffy

根拠がなければ(System V shでも動作します)、

case $string in
    ''|*[!0-9]*) echo bad ;;
    *) echo good ;;
esac

これは空の文字列と数字以外の文字を含む文字列を拒否し、他のすべてを受け入れます。

負数または浮動小数点数には追加の作業が必要です。最初の "bad"パターンで-/.を除外し、不適切な使い方を含む "bad"パターンを追加するという考えがあります(?*-*/*.*.*

243
jilles

以下の解決策は、正規表現を必要とせずにBourneなどの基本的なシェルでも使用できます。基本的に非数値を使った数値評価操作はエラーになりますが、これはShellでは暗黙のうちにfalseとみなされます。

"$var" -eq "$var"

のように:

#!/bin/bash

var=a

if [ -n "$var" ] && [ "$var" -eq "$var" ] 2>/dev/null; then
  echo number
else
  echo not a number
fi

あなたはまた$のためにテストすることができますか?より明示的な操作の戻りコード

[ -n "$var" ] && ["$var" -eq "$var"] 2>/dev/null
if [ $? -ne 0 ]; then
   echo $var is not number
fi

標準エラーのリダイレクトは、数値がない場合にbashが出力する「integer expression expected」メッセージを隠すためにあります。

_警告_ (下記のコメントのおかげで):

  • 小数点付きの数字は ではありません は有効な「数字」として識別されます
  • [[ ]]の代わりに[ ]を使用すると、常にtrueと評価されます。
  • ほとんどの非Bashシェルはこの式を常にtrueとして評価します。
  • Bashの動作は文書化されていないため、警告なしに変更される可能性があります。
  • bash: [[: 1 a: syntax error in expression (error token is "a")のように、数値の後にスペースが含まれている場合(例: "1 a")はエラーになります。
  • 値がvar-nameと同じ場合(例:i = "i")、bash: [[: i: expression recursion level exceeded (error token is "i")のようにエラーになります。
160

これは、数値が負でない整数であり、シェルから独立しているか(つまり、bashismsなしで)、シェル組み込みのみを使用するかどうかをテストします。

不正です。

この最初の答え(下記)では、最初の変数が変数の先頭ではない限り、文字を含む整数を使用できます。

[ -z "${num##[0-9]*}" ] && echo "is a number" || echo "is not a number";

_正しい_

jilles はコメントし、 彼の答えで提案しました これはシェルパターンを使用してそれを行うための正しい方法です。

[ ! -z "${num##*[!0-9]*}" ] && echo "is a number" || echo "is not a number";
39
mrucci

Bashの 拡張パターンマッチングを提案する人は誰もいません

[[ $1 == ?(-)+([0-9]) ]] && echo "$1 is an integer"
30
glenn jackman

Shellの数値フォーマットを直接解析するソリューションには驚いています。 Shellはこれにはあまり適していません。ファイルとプロセスを制御するためのDSLです。もう少し下位に十分な数のパーサーがあります。例えば:

isdecimal() {
  # filter octal/hex/ord()
  num=$(printf '%s' "$1" | sed "s/^0*\([1-9]\)/\1/; s/'/^/")

  test "$num" && printf '%f' "$num" >/dev/null 2>&1
}

'%f'を必要な特定の形式に変更してください。

27
pixelbeat

私は答えを見ていました、そして、誰も(ドットで)FLOAT数について考えなかったことに気付きました!

Grepを使うのも素晴らしいです。
- Eは拡張正規表現を意味します
- qは静かを意味します(エコーしません)。
- qEは両方の組み合わせです。

コマンドラインで直接テストするには

$ echo "32" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is: 32

$ echo "3a2" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is empty (false)

$ echo ".5" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer .5

$ echo "3.2" | grep -E ^\-?[0-9]?\.?[0-9]+$  
# answer is 3.2

Bashスクリプトで使う:

check=`echo "$1" | grep -E ^\-?[0-9]*\.?[0-9]+$`

if [ "$check" != '' ]; then    
  # it IS numeric
  echo "Yeap!"
else
  # it is NOT numeric.
  echo "nooop"
fi

JUST整数と一致させるには、これを使います。

# change check line to:
check=`echo "$1" | grep -E ^\-?[0-9]+$`
15
Sergio Abreu

@maryへのフォローアップ。しかし、私は十分な担当者を持っていないので、その記事へのコメントとしてこれを投稿することができませんでした。とにかく、これが私が使ったものです。

isnum() { awk -v a="$1" 'BEGIN {print (a == a + 0)}'; }

引数が数値の場合、この関数は "1"を返し、それ以外の場合は "0"を返します。これは浮動小数点数と同様に整数に対しても働きます。使い方は次のようなものです。

n=-2.05e+07
res=`isnum "$n"`
if [ "$res" == "1" ]; then
     echo "$n is a number"
else
     echo "$n is not a number"
fi
12
triple_r
test -z "${i//[0-9]}" && echo digits || echo no no no

${i//[0-9]}は、$iの値に含まれる任意の数字を空の文字列に置き換えます。man -P 'less +/parameter\/' bashを参照してください。 -zは、結果の文字列の長さがゼロかどうかを確認します。

$iが空の場合もこのケースを除外したい場合は、以下のいずれかの構成を使用できます。

test -n "$i" && test -z "${i//[0-9]}" && echo digits || echo not a number
[[ -n "$i" && -z "${i//[0-9]}" ]] && echo digits || echo not a number
7
user2683246

http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_03.html

Bashの文字クラスも使えます。

if [[ $VAR = *[[:digit:]]* ]]; then
 echo "$VAR is numeric"
else
 echo "$VAR is not numeric"
fi

数値には、スペース、小数点、および浮動小数点の場合は「e」または「E」が含まれます。

しかし、Cスタイルの16進数、つまり "0xffff"または "0XFFFF"を指定した場合、[[:digit:]]はtrueを返します。ここでちょっとした罠、bashはあなたが "0xAZ00"のようなことをすることを可能にし、それでも数字として数えます(16以外のベースに0x記法を使わせたGCCコンパイラの奇妙なことからではありませんか。 )

入力が完全に信頼されていない場合は、テストの前に "0x"または "0X"をテストして数値になるかどうかをテストすることをお勧めします。それは以下によって達成されるでしょう:

if [[ ${VARIABLE:1:2} = "0x" ]] || [[ ${VARIABLE:1:2} = "0X" ]]; then echo "$VAR is not numeric"; fi
7
ultrasawblade

昔の質問ですが、私は自分の解決策に取り組みたいと思いました。これは、奇妙なシェルトリックを必要としないか、永遠に存在しなかった何かに頼りません。

if [ -n "$(printf '%s\n' "$var" | sed 's/[0-9]//g')" ]; then
    echo 'is not numeric'
else
    echo 'is numeric'
fi

基本的にそれは単に入力からすべての数字を削除します、そしてあなたがゼロでない長さの文字列で残っているならそれは数字ではありませんでした。

7
Sammitch
[[ $1 =~ ^-?[0-9]+$ ]] && echo "number"

負の数を含めるために-を忘れないでください。

6
D_I

私はこれを試してみます:

printf "%g" "$var" &> /dev/null
if [[ $? == 0 ]] ; then
    echo "$var is a number."
else
    echo "$var is not a number."
fi

注:これはnanとinfを数値として認識します。

6
overflowed

まだコメントできないので、私は自分の答えを追加します。これは、bashパターン・マッチングを使用したglenn jackmanの答えの拡張です。

私が最初に必要としていたのは、数字を識別し、整数と浮動小数点数を区別することでした。関数定義は次のように推論しました。

function isInteger() {
    [[ ${1} == ?(-)+([0-9]) ]]
}

function isFloat() {
    [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
}

意図したとおりに動作するパターンを検証するために、ユニットテスト(shUnit2を使用)を使用しました。

oneTimeSetUp() {
    int_values="0 123 -0 -123"
    float_values="0.0 0. .0 -0.0 -0. -.0 \
        123.456 123. .456 -123.456 -123. -.456
        123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
        123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
        123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
}

testIsIntegerIsFloat() {
    local value
    for value in ${int_values}
    do
        assertTrue "${value} should be tested as integer" "isInteger ${value}"
        assertFalse "${value} should not be tested as float" "isFloat ${value}"
    done

    for value in ${float_values}
    do
        assertTrue "${value} should be tested as float" "isFloat ${value}"
        assertFalse "${value} should not be tested as integer" "isInteger ${value}"
    done

}

注:isFloatパターンは、小数点(@(.,))およびE記号(@(Ee))についてより耐性があるように変更できます。私のユニットテストは整数か浮動小数点数のいずれかの値のみをテストしますが、無効な入力はテストしません。

5
karttu

expr を使います。ゼロ以外の値にゼロを追加しようとすると、ゼロ以外の値が返されます。

if expr -- "$number" + 0 > /dev/null 2>&1
then
    echo "$number is a number"
else
    echo "$number isn't a number"
fi

非整数が必要な場合は bc を使用することは可能かもしれませんが、bcがまったく同じ動作をするとは思わないゼロ以外の数にゼロを追加するとゼロになり、ゼロの値も返されます。たぶんあなたはbcexprを組み合わせることができます。 bcを使用して$numberにゼロを追加します。答えが0であれば、exprを試して$numberがゼロでないことを確認してください。

5
David W.

私は最近これを改ざんしなければならなかったので、 karttu's のように単体テストで近づきます。私はコードを修正し、他の解決策も追加しました。結果を見るために自分で試してみてください。

#!/bin/bash

    # N={0,1,2,3,...} by syntaxerror
function isNaturalNumber()
{
 [[ ${1} =~ ^[0-9]+$ ]]
}
    # Z={...,-2,-1,0,1,2,...} by karttu
function isInteger() 
{
 [[ ${1} == ?(-)+([0-9]) ]]
}
    # Q={...,-½,-¼,0.0,¼,½,...} by karttu
function isFloat() 
{
 [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]
}
    # R={...,-1,-½,-¼,0.E+n,¼,½,1,...}
function isNumber()
{
 isNaturalNumber $1 || isInteger $1 || isFloat $1
}

bools=("TRUE" "FALSE")
int_values="0 123 -0 -123"
float_values="0.0 0. .0 -0.0 -0. -.0 \
    123.456 123. .456 -123.456 -123. -.456 \
    123.456E08 123.E08 .456E08 -123.456E08 -123.E08 -.456E08 \
    123.456E+08 123.E+08 .456E+08 -123.456E+08 -123.E+08 -.456E+08 \
    123.456E-08 123.E-08 .456E-08 -123.456E-08 -123.E-08 -.456E-08"
false_values="blah meh mooh blah5 67mooh a123bc"

for value in ${int_values} ${float_values} ${false_values}
do
    printf "  %5s=%-30s" $(isNaturalNumber $value) ${bools[$?]} $(printf "isNaturalNumber(%s)" $value)
    printf "%5s=%-24s" $(isInteger $value) ${bools[$?]} $(printf "isInteger(%s)" $value)
    printf "%5s=%-24s" $(isFloat $value) ${bools[$?]} $(printf "isFloat(%s)" $value)
    printf "%5s=%-24s\n" $(isNumber $value) ${bools[$?]} $(printf "isNumber(%s)" $value)
done

したがって、 isNumber() はダッシュ、コンマ、指数表記を含むため、整数と浮動小数点数ではTRUEを返します。一方、 isFloat() は整数値ではFALSEを返し、 isInteger( ) フロートでも同様にFALSEを返します。あなたの便宜のために、一つのライナーとしてすべて:

isNaturalNumber() { [[ ${1} =~ ^[0-9]+$ ]]; }
isInteger() { [[ ${1} == ?(-)+([0-9]) ]]; }
isFloat() { [[ ${1} == ?(-)@(+([0-9]).*([0-9])|*([0-9]).+([0-9]))?(E?(-|+)+([0-9])) ]]; }
isNumber() { isNaturalNumber $1 || isInteger $1 || isFloat $1; }
4
3ronco

最も簡単な方法は、数字以外の文字が含まれているかどうかを確認することです。あなたはすべての数字を何も置き換えずに長さをチェックします。長さがあればそれは数字ではありません。

if [[ ! -n ${input//[0-9]/} ]]; then
    echo "Input Is A Number"
fi
4
Andy

明確な答えは@charles Dufyらによって既に与えられています。純粋なbashソリューションは以下を使用するでしょう:

string="-12,345"
if [[ "$string" =~ ^-?[0-9]+[.,]?[0-9]*$ ]]
then
    echo $string is a number
else
    echo $string is not a number
fi

実数の場合、 基数点 の前に番号を付けることは必須ではありません。

浮動小数点数と科学的記数法(C/Fortranなどの多くのプログラムはこの方法でfloatをエクスポートする)をより完全にサポートするために、この行に追加すると便利です。

string="1.2345E-67"
if [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]?-?[0-9]+$ ]]
then
    echo $string is a number
else
    echo $string is not a number
fi

特定の型を探しているのであれば、数字の型を区別する方法になります。

string="-12,345"
if [[ "$string" =~ ^-?[0-9]+$ ]]
then
    echo $string is an integer
Elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*$ ]]
then
    echo $string is a float
Elif [[ "$string" =~ ^-?[0-9]*[.,]?[0-9]*[eE]-?[0-9]+$ ]]
then
    echo $string is a scientific number
else
    echo $string is not a number
fi

注:10進数表記と科学表記の構文要件をリストできます。1つは、基数としてコンマを使用できることと、「。」です。そして、そのような基数点は1つだけでなければならないと主張します。 [Ee] floatには2つの+/-符号があります。私はAuluの仕事からさらにいくつかの規則を学び、 '' ' - ' '-E-1' '0-0'のような悪い文字列に対してテストしました。これが我慢できそうな私のregex/substring/exprツールです:

parse_num() {
 local r=`expr "$1" : '.*\([.,]\)' 2>/dev/null | tr -d '\n'` 
 nat='^[+-]?[0-9]+[.,]?$' \
 dot="${1%[.,]*}${r}${1##*[.,]}" \
 float='^[\+\-]?([.,0-9]+[Ee]?[-+]?|)[0-9]+$'
 [[ "$1" == $dot ]] && [[ "$1" =~ $float ]] || [[ "$1" =~ $nat ]]
} # usage: parse_num -123.456
4
Aulo

これは、grepを使用して、問題の変数が拡張正規表現と一致するかどうかを確認することで実現できます。

テスト整数1120

yournumber=1120
if [ $(echo "$yournumber" | grep -qE '^[0-9]+$'; echo $?) -ne "0" ]; then
    echo "Error: not a number."
else
    echo "Valid number."
fi

出力:Valid number.

非整数1120aのテスト:

yournumber=1120a
if [ $(echo "$yournumber" | grep -qE '^[0-9]+$'; echo $?) -ne "0" ]; then
    echo "Error: not a number."
else
    echo "Valid number."
fi

出力:Error: not a number.


説明

  • grep-Eスイッチを使用すると、拡張正規表現'^[0-9]+$'を使用できます。この正規表現は、変数が[]のみを含み、変数の0-9から^終わりまでの$ゼロから9までの数字を含み、少なくとも+ 1文字。
  • grep-q quietスイッチは、何かを検出したかどうかにかかわらず、出力をオフにします。
  • $?は、前に実行されたコマンドの終了ステータスです。終了ステータス0は成功を意味し、それ以上はエラーを意味します。 grepコマンドの終了ステータスは、一致する場合は0、一致しない場合は1です。
  • $()は、別のコマンドを実行して出力を使用できるサブシェルです。

それをすべてまとめて、$()サブシェルで、echo変数$yournumber|grepにパイプして、-qスイッチは、-E拡張正規表現'^[0-9]+$'式と暗黙的に一致します。次に、echo$?終了ステータス。grepが正常に一致した場合は0、一致しなかった場合は1になります。

ここで、$()サブシェルの外でif条件に戻って、$()サブシェルからの0または1の出力を取得し、 -ne"0"と等しくありません。一致しなかった場合、終了ステータスは1になり、一致しない"0"になります。次に、echo "Error: not a number."を実行します。一致に成功した場合、終了ステータスの出力は0に等しく"0"になり、それ以外の場合はecho "Valid number."になります。


フロートまたはダブルの場合

Floatまたはdoubleの正規表現を'^[0-9]+$'から'^[0-9]*+\.?[0-8]+$'に変更するだけです。

テストフロート1120.01

yournumber=1120.01
if [ $(echo "$yournumber" | grep -qE '^[0-9]*+\.?[0-8]+$'; echo $?) -ne "0" ]; then
    echo "Error: not a number."
else
    echo "Valid number."
fi

出力:Valid number.

テストフロート11.20.01

yournumber=11.20.01
if [ $(echo "$yournumber" | grep -qE '^[0-9]*+\.?[0-8]+$'; echo $?) -ne "0" ]; then
    echo "Error: not a number."
else
    echo "Valid number."
fi

出力:Error: not a number.


ネガ用

負の整数を許可するには、正規表現を'^[0-9]+$'から'^\-?[0-9]+$'に変更するだけです。

負のfloatまたはdoubleを許可するには、正規表現を'^[0-9]*+\.?[0-8]+$'から'^\-?[0-9]*+\.?[0-8]+$'に変更するだけです。

2
Joseph Shih

Alberto Zaccagniの回答が好きです。

if [ "$var" -eq "$var" ] 2>/dev/null; then

重要な前提条件: - サブシェルが生成されていない - REパーサーが呼び出されていない - ほとんどのシェルアプリケーションが実数を使用していない

$varが複雑で(連想配列へのアクセスなど)、その数が負でない整数になる場合(ほとんどの場合)、これはおそらくより効率的ですか?

if [ "$var" -ge 0 ] 2> /dev/null; then ..
2
user3895088

ここで同じことを、ドットで区切った部分全体と小数部分をテストする正規表現で行いました。

re="^[0-9]*[.]{0,1}[0-9]*$"

if [[ $1 =~ $re ]] 
then
   echo "is numeric"
else
  echo "Naahh, not numeric"
fi
1
Jerome

それが私にとって最も実用的であると思われたので、私はultrasawbladeのレシピを試してみました、そしてそれを働かせることができませんでした。結局、私は別の方法を考え出しました。パラメータ置換の他のものと同様に、今回は正規表現の置き換えです。

[[ "${var//*([[:digit:]])}" ]]; && echo "$var is not numeric" || echo "$var is numeric"

$ varのすべての:digit:class文字を削除し、空の文字列が残っているかどうかをチェックします。つまり、元の文字は数字のみであることを意味します。

私がこれについて好きなのは、その小さなフットプリントと柔軟性です。この形式では、他のニーズに合うようにパターンマッチングを使用することができますが、区切りのない10進整数に対してのみ機能します。

1
ata

あなたも "let"を次のように使うことができます:

[ ~]$ var=1
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=01
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s a number
[ ~]$ var=toto
[ ~]$ let $var && echo "It's a number" || echo "It's not a number"
It\'s not a number
[ ~]$ 

しかし、私はこのスレッドでいくつかの答えのように "=〜" Bash 3+演算子を使うのが好きです。

1
Idriss Neumann
  • チェックする変数

    number=12345またはnumber=-23234またはnumber=23.167またはnumber=-345.234

  • 数値または非数値をチェック

    echo $number | grep -E '^-?[0-9]*\.?[0-9]*$' > /dev/null

  • 上記の終了ステータスに基づいて、さらなるアクションを決定します

    if [ $? -eq 0 ]; then echo "Numeric"; else echo "Non-Numeric"; fi

1
Atanu

David Wの回答 13年10月からのフォローアップ、exprname__を使用する場合、これはより良いかもしれません

test_var=`expr $am_i_numeric \* 0` >/dev/null 2>&1
if [ "$test_var" = "" ]
then
    ......

数値の場合、1を掛けると同じ値になります(負数を含む)。そうでなければ、あなたはnullname__を手に入れることができます。

1
Jon T

フォーマット文字列 "%f"または "%i"を指定した場合は、他の回答としてprintfを使用します。printfがチェックを行います。チェックをやり直すよりも簡単で、構文は単純で短く、printfはいたるところにあります。だから私の考えではそれはまともな選択です - あなたはまた物事の範囲をチェックするために次のアイデアを使うことができます、それは数をチェックするのに役立つだけではありません。

declare  -r CHECK_FLOAT="%f"  
declare  -r CHECK_INTEGER="%i"  

 ## <arg 1> Number - Number to check  
 ## <arg 2> String - Number type to check  
 ## <arg 3> String - Error message  
function check_number() { 
  local NUMBER="${1}" 
  local NUMBER_TYPE="${2}" 
  local ERROR_MESG="${3}"
  local -i PASS=1 
  local -i FAIL=0   
  case "${NUMBER_TYPE}" in 
    "${CHECK_FLOAT}") 
        if ((! $(printf "${CHECK_FLOAT}" "${NUMBER}" &>/dev/random;echo $?))); then 
           echo "${PASS}"
        else 
           echo "${ERROR_MESG}" 1>&2
           echo "${FAIL}"
        fi 
        ;;                 
    "${CHECK_INTEGER}") 
        if ((! $(printf "${CHECK_INTEGER}" "${NUMBER}" &>/dev/random;echo $?))); then 
           echo "${PASS}"
        else 
           echo "${ERROR_MESG}" 1>&2
           echo "${FAIL}"
        fi 
        ;;                 
                     *) 
        echo "Invalid number type format: ${NUMBER_TYPE} to check_number()." 1>&2
        echo "${FAIL}"
        ;;                 
   esac
} 

>$ var=45

>$ (($(check_number $var "${CHECK_INTEGER}" "Error: Found $var - An integer is required."))) && { echo "$var+5" | bc; }

1
user4401178

負の数を捉えるには:

if [[ $1 == ?(-)+([0-9.]) ]]
    then
    echo number
else
    echo not a number
fi
1
user28490

私はかなり短いバージョンを見つけました:

function isnum()
{
    return `echo "$1" | awk -F"\n" '{print ($0 != $0+0)}'`
}
1
mary
printf '%b' "-123\nABC" | tr '[:space:]' '_' | grep -q '^-\?[[:digit:]]\+$' && echo "Integer." || echo "NOT integer."

負の整数を受け付けない場合は、grepマッチングパターンの-\?を削除してください。

1
Ane Dijitak

私の問題では、ユーザーが誤ってテキストを入力していないことを確認する必要があるので、シンプルで読みやすいようにしました。

isNumber() {
    (( $1 )) 2>/dev/null
}

Manページによれば、これは私が欲しいことをほとんどします。

式の値がゼロ以外の場合、戻り状況は0です。

「数字の可能性があります」という文字列に対する厄介なエラーメッセージを防ぐために、エラー出力は無視します。

$ (( 2s ))
bash: ((: 2s: value too great for base (error token is "2s")
1
Hachi

Quick&Dirty:それが最もエレガントな方法ではないことは知っていますが、通常はゼロを追加して結果をテストします。そのようです:

function isInteger {
  [ $(($1+0)) != 0 ] && echo "$1 is a number" || echo "$1 is not a number"
 }

x=1;      isInteger $x
x="1";    isInteger $x
x="joe";  isInteger $x
x=0x16 ;  isInteger $x
x=-32674; isInteger $x   

$ 1が整数でない場合、$(($ 1 + 0))は0または爆弾を返します。例えば:

function zipIt  { # quick Zip - unless the 1st parameter is a number
  ERROR="not a valid number. " 
  if [ $(($1+0)) != 0 ] ; then  # isInteger($1) 
      echo " backing up files changed in the last $1 days."
      OUT="zipIt-$1-day.tgz" 
      find . -mtime -$1 -type f -print0 | xargs -0 tar cvzf $OUT 
      return 1
  fi
    showError $ERROR
}

注:スクリプト全体が爆弾になるようなフロートや混在型をチェックすることは考えていなかったと思います。 mrucciのソリューションとDuffyの正規表現を試してみるつもりです - それらはbashフレームワークの中で最も堅牢なようです...

1
WWWIZARDS

私は次のものを使う(整数の場合):

## ##### constants
##
## __TRUE - true (0)
## __FALSE - false (1)
##
typeset -r __TRUE=0
typeset -r __FALSE=1

## --------------------------------------
## isNumber
## check if a value is an integer 
## usage: isNumber testValue 
## returns: ${__TRUE} - testValue is a number else not
##
function isNumber {
  typeset TESTVAR="$(echo "$1" | sed 's/[0-9]*//g' )"
  [ "${TESTVAR}"x = ""x ] && return ${__TRUE} || return ${__FALSE}
}

isNumber $1 
if [ $? -eq ${__TRUE} ] ; then
  print "is a number"
fi
1
Marnix

Perlがインストールされていれば、この1つのライナーはシンプルで読みやすく拡張性があります。

Perl -se 'exit($n !~ /\d+/)' -- -n=a

ここにいくつかのテストがあります

Perl -se 'exit($n !~ /\d+/)' -- -n=a; echo $?
1
Perl -se 'exit($n !~ /\d+/)' -- -n=2; echo $?
0

それはかなり自己説明的ですが、ここでより多くの情報があります

  • -eは評価を有効にします
  • -sは後に引数を渡すことを可能にします - この場合-n
  • bashの0は成功ですので、!~は否定正規表現の一致演算子です。引数-nが数値の場合は正常終了します

これを関数でラップするとよいでしょう。ここではfloatを読むことができるより良いバージョンです。

is_number() { Perl -se 'exit($n !~ /^\d+(\.\d+)?$/)' -- -n="$1"; }
0
geckos