tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

【sh】シェルスクリプトのifで変数に入れたカラ文字のをtestコマンドで判定 - ついでに数値、文字列、ファイルの比較と略式をおさらい

はじめに

シェルスクリプトは必要あれば書きますが
都度調べればなんとなく書けちゃうので毎回google先生のお世話になってます。

よく忘れる中にif とtestコマンドでの判定があります。
シェルスクリプト内でカラ文字かどうかで分岐したかったのですが
すこしだけ詰まったのでこの気にメモして記憶のインデックスに。

おしな

  1. testコマンドおさらい
    • testコマンドとは
    • testコマンド書式
    • testコマンドの結果を見るには?
  2. よくある動かない問題
  3. 数値を比較してみる
  4. 文字列を比較してみる
  5. ファイルのチェックをしてみる
  6. 略式でtestコマンドしてみる
  7. カラ文字の判定をしてみる

1. testコマンドおさらい

testコマンド自体はさがせばくらでも情報があるので要点だけにはしょります

testコマンドとは

ファイル形式のチェックや値の比較を行う。
条件式 expr を評価した結果によって、 0 (真) または 1 (偽) を終了ステータスとして返す。 参考:http://kazmax.zpp.jp/cmd/t/test.1.html

testコマンドといっているくらいなのでシェルスクリプト内だけで使えるものではなく
通常のコマンドライン上でも使えます。

testコマンド書式

test [ expr ]

これだけ書いちゃうとよくわかりませんがexprには式が入るイメージですね

testコマンドの結果を見るには?

testコマンドを実行してもよしなに結果は表示してくれません。

※ 実行しただけではうんともすんとも言わない
# test "a"="b"
# 

結果はlinuxの特殊変数$?に格納されるので、それを使ってechoで表示します

# test "a" = "b"
# echo $?
1

# test "a" = "a"
# echo $?
0

特殊変数についてはこちらを参考に。
http://shellscript.sunone.me/variable.html

2. よくある動かない問題

ここまでで比較の仕方、結果の見方など使い方はわかったと思うので
よくある動かない問題を上記の例をもとに1つだけ書いておきます。

ちょっとしたことでもつまづくと時間取られますしね。

※ 文字列を比較。結果は偽(1)
# test "a" = "b"
# echo $?
1

※ 文字列を比較。結果は真(0)
# test "a" = "a"
# echo $?
0

※ 文字列を比較。ただし=の前後のスペースを消してみる。結果は偽(1)?
# test "a"="b"
# echo $?
0

と、こんな感じでスペースの有無で結果が変わってしまうことがあります。
後述する略式型でもスペースの有無でエラーになったりと融通が効かないんですよね(><)

とりあえず動かない場合はスペースを疑いましょう。

文字列比較でのうまくいかない例は文字列比較のところに記載してます

3. 数値を比較してみる

使い方はだいたい書いてしまったので、ここからはリファレンス的にたんたんとメモ。
ここには概要だけ書くとしてこちらが詳しくはこちらが参考になります。

比較演算子
オプション 数式で 意味
-eq num1=num2 等しければ真
-ne num1≠num2 等しくなければ真
-lt num1<num2 より小ならば真
-le num1≦num2 以下ならば真
-gt num1>num2 より大ならば真
-ge num1≧num2 以上ならば真
# test 1 -eq 1; echo $?
0

# test 1 -eq 2; echo $?
1

# test 1 -ne 1; echo $?
1

4. 文字列を比較してみる

こちらは簡単で比較演算子=!=がほとんどです。

比較演算子
オプション 使用例 意味
= "hoge" = "hoge" 等しければ真
=! "hoge" = "fuga" 等しくなければ真
-z 文字列長が0なら真
-n 文字列長が 0 より大ならば真
# test "a" = "a"; echo $?
0

# test "a" = "b"; echo $?
1

# test "a" != "a"; echo $?
1

※ 変数に入れてからやってみる
# v="hoge"
# echo $v
hoge

# test $v = "hoge"; echo $?
0

# test $v = "fuga"; echo $?
1
文字列比較での動かない例

文字列比較でうまくいかない良くある例は、
何かのコマンドの結果文字列を変数に入れたりしたときが多いです。

文字列にスペースがある場合
※ echoの結果(文字列の間にスペースがあったり)を変数に入れる
# v=`echo aiu eo`
# echo $v
aiu eo

# test $v = "aiu eo"; echo $?
-bash: test: 引数が多すぎます
2

※ $vを文字列(" ")で囲むと大丈夫
# test "$v" = "aiu eo"; echo $?
0
文字列がカラの場合
※ echoの結果(カラ文字)を変数に入れる
# v=`echo`
# echo $v

# test $v = ""; echo $?
-bash: test: =: unary operator expected
2

※ $vを文字列(" ")で囲むと大丈夫
# test "$v" = ""; echo $?
0

※ エラーが出てくれればいいが、-zや-nオプションで比較すると困ることが。
※ -nオプションなので1文字以上なら真、カラ文字なら偽なので今回は1を期待のはずが。。。
# test -n $v; echo $?
0

※ $vを文字列(" ")で囲むと大丈夫
# test -n "$v"; echo $?
1

-zとか-nオプションを使ったときはエラーにもならないので
気づかずバグっぽくなりそうなのが怖い(><)

イコールの前後にスペース入れ忘れた上に""で囲まなかったりしたら
そのまま動く上に結果は正しくないので混乱しそうですね

※ スペース抜かすと意図しない挙動に。
※ スペースいれたら入れたでエラーになってしまうという。。。
# test $v!=""; echo $?
0

# test $v != ""; echo $?
-bash: test: !=: unary operator expected
2

※ しつこいけど合ってるのは1.スペース入れて2.だぶるクオートで囲む
# test "$v" != ""; echo $?
1

5. ファイルのチェックをしてみる

比較演算子
オプション 使用例 意味
-f test -f file 通常ファイルなら真
-d test -d file ディレクトリなら真
-s test -s file 0より大きいサイズなら真
-e test -e file 存在するなら真
-r test -r file 読み取り可能なら真
-w test -w file 書き込み可能なら真
-x test -x file 実行可能なら真
-x test file1 -nt file2 file1の方が新しければ真。is newer thanの略
-x test file1 -ot file2 file2の方が古ければ真。is older theの略
# touch test.txt

# test -f test.txt; echo $?
0

# test -f testtest.txt; echo $?
1

# ls -al test.txt
-rw-rw-r-- 1 hoge hoge 0  1月 22 15:41 2015 test.txt

# test -r test.txt; echo $?
0

# test -w test.txt; echo $?
0

# test -x test.txt; echo $?
1

6. 略式でtestコマンドしてみる

testコマンドは略式の[ ]を使用して記述できるのでそちらでやってみます。
判定式はtestコマンドとまったく同じです

※ 数値の比較
# [ 1 -eq 1 ]; echo $?
0

# [ 1 -eq 2 ]; echo $?
0

※ 文字列の比較
# [ "hoge" = "hoge" ]; echo $?
0

# [ "hoge" != "hoge" ]; echo $?
1

※ 括弧内に全部スペース無いと。。。
# ["hoge"!="hoge"]; echo $?
-bash: [hoge!=hoge]: コマンドが見つかりません
127

# 条件式の外側だけスペースいれると結果1のはずが。。
# [ "hoge"!="hoge" ]; echo $?
0

ここでもやっぱりスペースだいじ!

7. カラ文字の判定をしてみる

文字列判定のところで思わずカラ文字の判定もやっちゃってましたが
一応本題なので書いておきます。

※ 生のカラ文字を判定
# test "" = ''; echo $?
0

※ -zオプションでカラ文字を判定
# test -z ""; echo $?
0

※ 単純に変数に入れてカラ文字を判定
# v=""
# test "$v" = ""; echo $?
0

※ echoの結果(カラ)を変数に入れて判定
# v=`echo`
# test -z "$v"; echo $?

おわり

思ったより長くなって書くのが疲れた(><)
とにかくこれだいじ(><)

  • イコールの間はスペースいれる
  • 変数はだぶるクオートで加工

と、いうものの[ ]ではなく[[ ]]を使うという方法もあるので
気になる場合はこちらも参考に。疲れたから[[ ]]については書けませんでしたorz
test と [ と [[ コマンドの違い

しかし終わってみたらシェルスクリプトほとんど関係なかった