シェルスクリプト総合 その7
http://pc8.2ch.net/test/read.cgi/unix/1157601611/
からの転載。
http://pc8.2ch.net/test/read.cgi/unix/1157601611/
からの転載。
113 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 10:54:57 シェル内の変数が0の時の挙動についておしえてください。 Windowsで使う下記のような内容のバッチファイルを作るために、 Solaris8上で簡単なスクリプトを作成しますた。 <バッチファイルの中身 (期待している実行結果)> lha32 a D:¥save¥0.lzh D:¥work¥0¥ lha32 a D:¥save¥1.lzh D:¥work¥1¥ lha32 a D:¥save¥2.lzh D:¥work¥2¥ : lha32 a D:¥save¥9999.lzh D:¥work¥9999¥ (←9999部分は、実際は第1引数で指定) <作ったスクリプト> #!/bin/sh COUNT=0 LAST=$1 while [ $COUNT -le $LAST ] do echo "lha32 a D:¥¥save¥¥$COUNT.lzh D:¥¥work¥¥$COUNT¥¥" COUNT=`expr $COUNT + 1` done 114 続き sage 2006/10/07(土) 10:55:42 ところがこのスクリプトを実行すると、最初に実行されるCOUNT変数が0のときに 0の値が消えてしまう現象が出てしまいまつ。(´・ω・`) <shの実行結果> lha32 a D:¥save.lzh D:¥work ←0が消えている lha32 a D:¥save¥1.lzh D:¥work¥1¥ lha32 a D:¥save¥2.lzh D:¥work¥2¥ : 試しにシェルの種類を変えてみたところ、ksh, zsh は sh と同じ挙動を示し、 bashのみ期待していた出力となりますた。 <bashの実行結果> lha32 a D:¥save¥0.lzh D:¥work¥0¥ lha32 a D:¥save¥1.lzh D:¥work¥1¥ lha32 a D:¥save¥2.lzh D:¥work¥2¥ : この現象について、 ・何故、0が消えるのか? ・/bin/shを使った場合に0を表示させる方法 について教えてください。 おまいら、よろしくおながいします。 115 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 11:39:34 man echo 116 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 11:50:42 >>113 それは、echoコマンドの仕様が違うため。 Solarisなどの /bin/sh の echo は、bashの echo -e に相当する。 echo -e 相当だと、¥ が、シェルと echoで2回解釈されるので、 単純な ¥ を出力させたければ、¥¥¥¥ と書かないと行けない。 よって↓で桶。 echo "lha32 a D:¥¥¥¥save¥¥¥¥$COUNT.lzh D:¥¥¥¥work¥¥¥¥$COUNT¥¥¥¥" 117 113 sage 2006/10/07(土) 12:08:24 >>116 回答ありがとうございますた。 ¥がシェルと echoで2回解釈されるとは知りませんですた…。 118 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 12:10:55 ¥0になりうる場所のみ二重化すればよいから、 echo "lha32 a D:¥¥save¥¥¥¥$COUNT.lzh D:¥¥work¥¥¥¥$COUNT¥¥" でもいいな。 119 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 12:42:08 >>118 ashとかだと、¥1 でも 8進数の1と解釈するから、それはお勧めできない。 すべて ¥¥¥¥ にするのが吉。 120 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 13:00:20 エスケープだらけでややこしいな。 echo時は無難な/にでもしといて |sed とかしてまとめてエスケープつけると 見やすいかも。好きずきだが。 121 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 13:02:25 ash(´゜c_,゜` )プッ んな中途半端なもん使うなや それに¥1になりうるのは¥¥$COUNTのところだけだろ。 122 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 13:22:46 D:¥¥save じゃなくて、 D:¥¥tave とかだったら困るだろ。 ¥¥¥¥ にしとけ。 123 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 13:24:36 UNIXのコマンドは¥をエスケープキャラクタとして使用するものが多い。 ディレクトリ区切りは/としておいて、最後に一括変換すればよい。 #!/bin/sh COUNT=0 LAST=$1 while [ $COUNT -le $LAST ] do echo "lha32 a D:/save/$COUNT.lzh D:/work/$COUNT/" COUNT=`expr $COUNT + 1` done | tr '/' '¥¥' 124 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 13:38:18 ¥(´゜c_,゜` )プッ んな中途半端なもん使うなや 125 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 19:02:19 適当に'~'を混ぜて、¥の部分をシェルには解釈させないようにすればいい。 というかむしろ変数展開部分だけ"~"使え。ややこしいときは。 echo lha32 a 'd:¥¥save¥¥'"$COUNT.lzh" 'd:¥¥work¥¥'"$COUNT"'¥¥' 126 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 20:28:15 echo に関してだけはbashがGJだとおもうな。 printf があるのに、エスケープシーケンスを解釈してしまうようなままにしとくのがいけない。 バッドノウハウの典型だな。 127 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 20:32:36 やっぱ bash使えば直るよねぇ 128 名無しさん@お腹いっぱい。 sage 2006/10/07(土) 22:39:17 echoがエスケープシーケンス解釈しないのはBSD由来なわけだが。 んで、echoがエスケープシーケンスをデフォルトで解釈するビルドもできちゃう どっちつかずなbashがGJなのかよw 129 名無しさん@お腹いっぱい。 sage 2006/10/08(日) 00:09:40 デフォルトは有効でもいいが、オプションで無効にできたりするといいがな。 130 名無しさん@お腹いっぱい。 sage 2006/10/08(日) 01:13:22 大多数のshができないものは基本無効、オプションで有効だろ? 131 名無しさん@お腹いっぱい。 sage 2006/10/08(日) 06:43:25 ちゃうだろ。 Solarisなどのecho(/bin/echoも含む)が、エスケープシーケンスを無効にする方法がないことをいってるんジャマイカン?
※コメント投稿者のブログIDはブログ作成者のみに通知されます