質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

Q&A

解決済

4回答

5190閲覧

シェルスクリプトで、パラメータの空文字""を検出したい

umino

総合スコア54

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

CentOS

CentOSは、主にRed Hat Enterprise Linux(RHEL)をベースにした、フリーのソフトウェアオペレーティングシステムです。

シェルスクリプト

シェルスクリプトは、UNIX系のOSもしくはコマンドラインインタプリタ向けに記述されたスクリプト。bash/zshといったシェルによって実行されるため、このように呼ばれています。バッチ処理などに使用されており、テキストファイルに書かれた命令を順に実行します。

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

0グッド

0クリップ

投稿2020/05/08 09:34

前提・実現したいこと

シェルスクリプトtest.shにパラメータを4つ渡し、
パラメータが1つでも空文字"" の場合は不正として終了したいです。

正常時の実行イメージ
sh test.sh 10 15 2 30

例えばパラメータを下記に設定した場合、エラーにしたい。
sh test.sh 10 15 "" 30

なお「パラメータの個数が4つかどうか」は他の処理でチェックしているので、
確認したいのは「パラメータに空文字""が渡っていないか」だけです。

試したこと

bash

1#!/bin/bash - 2## IFパラメータ空文字チェック 3for v in $1 $2 $3 $4 4do 5 eval val=$${v}; 6 if [ -z ${val} ]; then 7 echo"パラメータに空文字を含んでいるため、登録できません" 8 exit 1 9 fi 10done 11 12echo "テストは成功です"

-xvオプションを付与して実行した場合、下記のような結果になりました。

console

1 2# sh -xv UnitSyncWebSettingCron.sh 10 15 "" 30 3## IFパラメータ空文字チェック 4for v in $1 $2 $3 $4 5do 6 eval val=$${v}; 7 if [ -z ${val} ]; then 8 echo"パラメータに空文字を含んでいるため、登録できません" 9 exit 1 10 fi 11done 12+ for v in '$1' '$2' '$3' '$4' 13+ eval 'val=$10' 14val=$10 15++ val=100 16+ '[' -z 100 ']' 17+ for v in '$1' '$2' '$3' '$4' 18+ eval 'val=$15' 19val=$15 20++ val=105 21+ '[' -z 105 ']' 22+ for v in '$1' '$2' '$3' '$4' 23+ eval 'val=$30' 24val=$30 25++ val=0 26+ '[' -z 0 ']'

変数が思うように展開されていないように見えるのですが、どのように書けば正しく展開できるか、解決方法がわかりません。
お詳しい方、よい書き方をご教示願えませんでしょうか。
よろしくおねがいします。

補足情報(FW/ツールのバージョンなど)

GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

count=0 while [ $count -lt $(($#)) ]; do n=$count eval val=$$count if [ -z ${val} ]; then echo "パラメータに空文字を含んでいるため、登録できません" exit 1 fi ((count++)) done echo $*

興味深かったので書いてみました。
このままだと引数の数が不定っぽかったので、 比較のため $(($#)) を引数の数にしてループさせています。

投稿2020/05/08 10:34

tetsunosuke

総合スコア1292

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

umino

2020/05/08 10:56

tetsunosukeさん ご回答ありがとうございます。 頂いたコードで試してみたところ、期待した結果を得ることができました。 普段わたしが知らないような書き方で、大変勉強になりました。 丁寧なご回答、ありがとうございます。 count=0 + count=0 while [ $count -lt $(($#)) ]; do n=$count eval val=$$count if [ -z ${val} ]; then echo "パラメータに空文字を含んでいるため、登録できません" exit 1 fi ((count++)) done + '[' 0 -lt 4 ']' + n=0 + eval 'val=$0' val=$0 ++ val=test.sh + '[' -z test.sh ']' + (( count++ )) + '[' 1 -lt 4 ']' + n=1 + eval 'val=$1' val=$1 ++ val=10 + '[' -z 10 ']' + (( count++ )) + '[' 2 -lt 4 ']' + n=2 + eval 'val=$2' val=$2 ++ val=15 + '[' -z 15 ']' + (( count++ )) + '[' 3 -lt 4 ']' + n=3 + eval 'val=$3' val=$3 ++ val= + '[' -z ']' + echo パラメータに空文字を含んでいるため、登録できません
tetsunosuke

2020/05/08 11:10

あ、n=$count はいらんかった。試しながら書いていたので名残ですw 自分も $(($#)) は知らなかったのでためになりました。
guest

0

ベストアンサー

""で囲めば良いです。

Bash

1#!/bin/bash - 2## IFパラメータ空文字チェック 3for v in "$1" "$2" "$3" "$4" 4do 5 if [ -z "$v" ] 6 then 7 echo "パラメータに空文字を含んでいるため、登録できません" 8 exit 1 9 fi 10done 11 12echo "テストは成功です"

投稿2020/05/08 10:38

otn

総合スコア84423

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2020/05/08 10:40

個数が4であることを別途確認しているということなので、 for v in "$@" でもいいです。
umino

2020/05/08 10:52

otnさん ありがとうございます。いま頂いたコードで試したところ、無事期待する結果が得られました。 わたしは""をつけていないうえ、不要な処理を入れていました。 丁寧に示していただいて助かりました。ありがとうございます。
umino

2020/05/08 10:53

なるほどですね。 プラスアルファまでありがとうございます。改修しやすいよう、"$@"でやろうとおもいます。
otn

2020/05/08 11:01

「空かも知れない」「空白文字を含んでいるかも知れない」という場合は "" で囲みます。 希に、「空なら、(空文字列で無く)空(=何も無いこと)になって欲しい」「空白文字を含んでいれば複数文字列に分かれて欲しい」というケースがあり、その場合だけ囲みません。
umino

2020/05/08 11:07

なるほどですね、いままでは「展開後もひとつの文字列として扱いたい場合は""で囲うんだ」と勝手に思っていたのですが、「空かも知れない」「空白文字を含んでいるかも知れない」という場合は ""で囲う、というお話を伺って、正しいイメージができたと思います。 メモしておいて、今後コーディングの際に見返します。 わかりやすく教えていただき、ありがとうございました。
otn

2020/05/08 11:23 編集

> いままでは「展開後もひとつの文字列として扱いたい場合は""で囲うんだ」 文章としては、それで合ってます。 A="" の $Aを、「空でなく、1つの空文字列として扱いたい」 A="1 2" の $Aを、「2つでなく、1つの文字列として扱いたい」 ということなので。
guest

0

こうする必要があるのではないでしょうか。

for v in "$1" "$2" "$3" "$4" ...

投稿2020/05/08 10:25

KojiDoi

総合スコア13669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

umino

2020/05/08 10:59

KojiDoiさん ご回答ありがとうございます。 変数を囲うのみだと、期待する結果が得られませんでした。 ↓の部分にも修正を加え、 for v in $1 $2 $3 $4 do eval val=$${v}; if [ -z ${val} ]; then ----------------- for v in "$1" "$2" "$3" "$4" do if [ -z "$v" ] ... とすることで、期待する結果を得ることができました。 ご回答、ありがとうございました。
guest

0

こういう感じになります。

sh

1#!/bin/sh 2 3i=1 4while [ $i -lt 5 ]; do 5 eval "v=${$i}" 6 if [ -z $v ]; then 7 echo "void argument" 8 else 9 echo $v 10 fi 11 i=`expr 1 + ${i}` 12done

for 文で回そうとすると、

sh

1sh test.sh 10 15 "" 30

はスクリプト中で

sh

1for 10 15 30

と展開されてしまいます。

投稿2020/05/08 10:14

cugel

総合スコア220

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

umino

2020/05/08 10:47 編集

なるほどですね、空文字はスクリプト内ではない(というと正しいのかはわかりませんが)扱いになるのですね。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問