shシェル:case文のワイルドカードのエスケープについて(再)

このQ&Aのポイント
  • shシェルスクリプトのcase 文のワイルドカードのエスケープについて質問させて下さい。
  • "$i" の内容に関して、1番目はYまたはyの後に文字通り*、2番目はYまたはyで始まる任意の文字列、3番目は文字通り [Yy]*、4番目は文字通り [Yy] で始まる任意の文字列の場合分けという理解でよろしいでしょうか。
  • シェルスクリプトの良書として評価されている「入門UNIXシェルプログラミング 改訂第2版」において、説明が正確でないと感じております。正しい場合分けは[Yy]、[Yy]"*"、[Yy]*ですが、この本の説明は間違っている可能性があります。
回答を見る
  • ベストアンサー

shシェル:case文のワイルドカードのエスケープについて(再)

shシェルスクリプトのcase 文のワイルドカードのエスケープについて質問させて下さい。 (初め「プログラミング > その他(プログラミング)」で質問しましたが、 プログラムと言うよりもシェルの話しなのでこちらに移しました。) #!/bin/sh case "$i" in [Yy]"*" ) echo "Y(literary *) or y(literary *)" ;; [Yy]* ) echo "Y(wild-card *) or y(wild-card *)" ;; "[Yy]*" ) echo "(literary [Yy]*)" ;; "[Yy]"* ) echo "(literary [Yy])(wild-card *)" ;; esac とした場合、"$i" の内容に関し、 1番目は、Yまたは yの後に文字通り* 2番目は、Yまたは yで始まる任意の文字列 3番目は、文字通り [Yy]* 4番目は、文字通り [Yy] で始まる任意の文字列 の場合分けという理解でよろしいでしょうか。 私のシステム GNU bash, version 2.05b.0(1)-release (i386-redhat-linux-gnu) で走らせると、上のように振舞うように思うのですが、 現在読んでいる ブルース・ブリン 「入門UNIXシェルプログラミング 改訂第2版」(ソフトバンク) 第5刷、p34 の説明で "[Yy]" ) の説明が 「これはYあるいはyに限る」 "[Yy]*" ) は 「これはY* あるいは y* と言う文字に限る」 "[Yy]"* ) は 「Y か y で始まる文字列 」 と説明されているので、疑問に思いました。 私が正しく理解していれば、上の説明は誤りで、上の3つの説明に合うのは、 それぞれ、 [Yy] ) [Yy]"*" ) [Yy]* ) であるはずなのですが、いかがでしょう。 この本はシェルスクリプトの良書としてよく読まれているようで、 しかも第2版でこんな間違いをするかなぁ?とも思いまして。 ひょっとして私がなにか誤解していますでしょうか? よろしくお願いします。

noname#9431
noname#9431

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

良く読まれてますね~ 私は初版を持っているのですが、確かにそう掛かれていますね。でも同書 p.11 を見る限り、ダブルクォートで囲った場合には [ も ] もただの文字扱いになると書いてありますし、p.34 の方は間違いだと思います。

noname#9431
質問者

お礼

>でも同書 p.11 を見る限り、ダブルクォートで囲った場合には [ も ] もただの文字扱いになると書いてありますし、 そうなんです! それで、読み進んでこの例を見て、え?! と思ったのです。 p11の説明を読んで、けっきょく「"」は、例えば、$STRINGとか`cat list.txt' などの「代入」を生かしたいときの他はほとんど「'」と同じね、とインプットされていたもので、矛盾するヤン!と思ったのです。 しかし、p34の間違い方が単なるミスプリレベルでないのでおかしいなあ?と思ったわけなのですが、 やっぱり間違いみたいですね。 (それとも、同じsh系シェルでもこの点の振舞いにちがいがあるのかなー。) とりあえず、私の理解は間違っていないようなので安心しました。ありがとうございました。

その他の回答 (1)

回答No.2

No.1 ですが、 > (それとも、同じsh系シェルでもこの点の振舞いにちがいがあるのかなー。) 私は FreeBSD の /bin/sh で試して、同じ結果でした。Linux と違って FreeBSD の /bin/sh は bash ではないので、少なくとも bash 固有の現象(?)ではないと思います。 # が、FreeBSD の /bin/sh も純粋な Bourne Shell では # 無いらしいので、純粋な Boure Shell だと挙動が # p.34 のようになるのかもしれませんね。

noname#9431
質問者

お礼

再びありがとうございます。 そうですか、少くともbash特有の現象ではないことも分かり参考になりました。 とりあえず出版社にメールしてみました。 ありがとうございました。

関連するQ&A

  • Emacsのシェルモードでワイルドカードが使えない

    こんにちは。 Emacsは、Gnu Emacs for Windows 23.4 を使っています。 シェルモードのシェルには、cygwinのbashを使っているのですが、 bashで使えるはずのワイルドカードが、いくつか使えなくて、困っています。 bashのワイルドカードで、使えないものは、以下の通りです。 ?(pattern) 与えられたパターンが 0 回または 1 回現われるとマッチします。 *(pattern) 与えられたパターンが 0 回以上現われるとマッチします。 +(pattern) 与えられたパターンが 1 回以上現われるとマッチします。 !(pattern) 与えられたパターンいずれにも含まれないもの全てにマッチします。 これらのワイルドカードは、ktermなどの上では、きちんと使えます。 例えばkterm上で、 echo !(*.c) と打てば、.cで終わらないファイル名を持つ、ファイルの一覧が表示されます。 ところが、Emacsのシェルモードで、同じように echo !(*.c) と打つと、 emacs "bash: !: event not found" と表示されます。 同様に、 echo *(.c) と打った場合、 bash: 期待してない token `(' のあたりにシンタックスエラー と表示されます。 どうすれば、こういったワイルドカードを、シェルモードで使う事ができるのでしょうか? 何か御存じの方がいらっしゃれば、是非、情報を提供して頂きたく思います。 では、よろしくお願い致します。

  • シェルスクリプトで配列が使えない

    シェルスクリプトを利用するときに変数を配列として扱えるという記述を見たので、 以下のようなシェルスクリプトを作成したのですが、エラーが出てきてしまいます。 端末で直接入力すると、正しく動作します。そのためなぜエラーとなるのかわかりません。 環境はubuntu 10.10、 GNU bash, バージョン 4.1.5(1)-release (i686-pc-linux-gnu) です。 ---------------------- #!/bin/sh list=(`ls`) echo ${list[0]} ---------------------- 3:Syntax error: "(" unexpected

  • ファイルから文字列を読み込むシェルスクリプトの作成

    現在シェルスクリプトの勉強をしています。 ファイルから文字列を読み込み表示するだけのシェルスクリプトを 作成しているのですが、エラーが出てうまくいきません。 ./test.sh: line 10: syntax error near unexpected token `done' 以下の通りファイルを作っています。 改行コードはLF、文字コードはSJISとなっています。 どのあたりが間違っているのか教えて頂けますでしょうか。 よろしくお願いします。 test.sh --------------------- #!/bin/sh LIST=./abc.lst while read F1 echo ${F2} break done < ${LIST} } --------------------- abc.lst --------------------- AAA BBB CCC ---------------------

  • シェルスクリプト文字列の処理について

    はじめましてよろしくお願いします。 質問サイトもシェルも初心者なので至らない点がございましたら ご容赦の程よろしくお願いします。 下記シェルスクリプトを実行すると下記エラーが発生します。 「test2」変数に空白無しで「abc」と入力するとエラーは発生しません。 変数test2の値(a bc)を変更せずにエラーが発生しない方法はないでしょうか? 手段でもかまいませんので教えてください。 ========================= testsh110207.sh ====================================== #!/bin/sh test1="abc" test2="a bc" if [ ${test1} = ${test2} ] then echo "=:文字列1と文字列2が等しい場合に真" echo "test1の「${test1}」と、test2の「${test2}」は等しい" fi if [ ${test1} != ${test2} ] then echo "!=:数値1と数値2が等しくない場合に真" echo "test1の「${test1}」と、test2の「${test2}」は等しくない" fi echo "********* テスト完了 *********" ======================================================================= $ ./testsh110207.sh ./testsh110207.sh: line 6: [: too many arguments ./testsh110207.sh: line 13: [: too many arguments ********* テスト完了 *********

  • Kシェルが動作しない。

    Kシェルが動作しない。 以下シェル自体ですが、単体では動作するのですが、メインのシェルから呼び出すと動作しなくなります。 動作しない条件としては、子シェルがメインシェルのwhile文の中に入れていると無限ループ???してしまいます。(for文やそれ以外では動作します。) なにかご存知でしたら、ご教授願います。 ・子シェル(Yes or Noを入力するまで無限ループする) #!/bin/ksh answer= echo "Do you add xxxx ? ---> [y/n]\c" while : do if [ "`echo -n`" = "-n" ]; then echo "$@\c" else echo -n "\@" fi read answer case "${answer}" in [yY] | yes | YES | Yes ) return 0 ;; [nN] | no | NO | No ) return 1 ;; * ) echo "Please enter y or n." ;; esac done ・メインシェル #!/bin/ksh while read line do /xxx/子シェル.ksh done < /xxx/zzz.txt 分かりづらいかも知れませんが、ご容赦願います。

  • シェルスクリプト内での四則演算

    非常に基本的な事だと思うのですが、どうしても解決できないので質問させてください。 シェルスクリプトで四則演算をしたいです。expr を使って下記の通りに書きました。 ---------------- #!/bin/sh echo $1 echo $2 AA='expr $1 + $2' echo "$AA" ---------------- これを test.sh として保存し、 $ sh test.sh 1 2 と試してみると、出力が ---------------- 1 2 expr $1 + $2 ---------------- となります。最後の行は 3 になってもらいたいのですが。 ちなみに、普通にコマンドプロンプトで $ expr 1 + 2 とやれば 3 と出てきます。 環境は Ubuntu 9.04 よろしくお願いします。

  • 【シェル】while文の変数定義について

    OS:Solaris10 sh:Bシェル お世話になります。 シェルの冒頭で定義した変数をwhile文の中で読み込ませたいです。 現状のシェルは下記の通りです。 ---- #!/bin/sh # *** 変数定義 *** AAA1=Spring BBB1=Summer AAA2=Autumn BBB2=Winter # *** メイン処理 *** i=1 while [ $i -le 2 ]; do AAA=AAA$i BBB=BBB$i echo ${AAA} echo ${BBB} i=`expr $i + 1` done ---- しかし、出力される結果は下記のようになってしまいます。 AAA1 BBB1 AAA2 BBB2 これを冒頭の「*** 変数定義 ***」で定義した値を読み込ませ、下記のような出力結果を得たいです。 Spring Summer Autumn Winter どうかご教授ください。

  • 【シェル】チルダの置換

    こんばんは。 Cシェルで1文字単位で置換する場合なのですが、 A→Y B→" C→3 D→~ のように対応しているファイルを読み込んで合致したらその文字に置換という方法にしています。その場合、D→~なので、ホームディレクトリが格納されてしまいます。 例えば、「ADC」という文字列があったら、「Y~3」というように置換したいのですが、「Y***/###3」のようになってしまいます。置換の際はechoとsedを使って、一度ファイルに落とし、それをまた変数に格納しています。 また、{や0もうまく読み込んでくれませんでした。クォーテーションでくくるとクォーテーションごと格納されました。("~" or '~') ファイルの方に\をつけて、\~でもうまくいきませんでした。 なんだか支離滅裂な文章ですが、ご存知の方いらっしゃいましたらどうぞ宜しくお願いします。

  • シェルスクリプトで、空白(スペース)を含む変数をawkに渡したいのです

    シェルスクリプトで、空白(スペース)を含む変数をawkに渡したいのですが、どうしたらいいでしょうか? 例えば、以下のようなtest.shというファイルを作ったとします。 --------------- #!/bin/sh AAA="x y" echo "" | awk '{print $AAA}' -------------- としたとき、$AAAが正常に出力できません。(なお、echo "" は、awkを走らせる為の単なるダミーです。) printの部分を ・awk '{print '$AAA'}' ・awk '{print "'$AAA'"}' などともしてみましたが、ダメでした。どのようにすればうまくいくでしょうか?

  • if [ 条件式 ]とif[[ 条件式 ]]

    シェルスクリプトでのif [ 条件式 ] と if [[ 条件式 ]] の違いについて教えてください。 以下のシェルスクリプトを実行すると、 意図したとおり、111 と出力されます。 =========▼▼(ここから)▼▼========= #!/bin/sh AAA=yes if [[ "$AAA" = [yY]* ]] then echo 111 else echo 222 fi =========▲▲(ここまで)▲▲========= 上記、スクリプト3行目の if [[ "$AAA" = [yY]* ]] の部分を if [ "$AAA" = [yY]* ] というように、角カッコ 1重にすると、 エラーは発生しませんが、 222と表示されます。 if [ 条件式 ] と if [[ 条件式 ]] の違いについて教えていただけないでしょうか。