«前の日記(2006年9月11日(月)) 最新 次の日記(2006年10月10日(火))» 編集

徒然日記


2006年9月23日(土) [長年日記]

shell scriptのwhile

仕事でshell script書いてたんすよ。だけど、どうにもうまく動かない。

それで挙動を追ってるとwhileの中で変数に代入した値が、ループの外だと空になってる。

さらに、試してみるとwhileの外である変数に代入して、ループの中でも代入を行うと、ループの中では新たに代入された値になるんだけど、外に出ると始めに代入した値に戻ってしまう。

なんでshell scriptなのにscopeをもってるかのように振る舞うんだ?

shell scpriptって全部Global変数でしょ?とか、先輩と一緒に悩んだりしていたのだが、shell scriptの得意な人に聞いたら

「whileの中の変数は外に出せないよ。まるでsopeみたいに。

困るんだよねぇ、ファイルに吐くとかすると効率が悪いし」との事でした

2時間は悩んでた〜〜orz

実例

わかりにくい人のために実例

#!/bin/sh
A=1
echo "out of loop 1, A: $A"
echo "hoge" | while read line ; do
   echo "in the loop 2, A: $A"
   A=2
   echo "in the loop 2, A: $A"
done
echo "out of loop 2, A: $A"

これを実行すると…

$ ./test.sh                                                                  
out of loop 1, A: 1
in the loop 2, A: 1
in the loop 2, A: 2
out of loop 2, A: 1

こうなる

キモイ

キモすぎる〜〜〜〜

今回の敗因

ファイルから1行ずつ読み込んで、該当行があったら抜けて、次の処理に移る。whileはさっさと抜ける、という感じで書いたことだろか…

結局変数を参照するところまで全てwhileでくくって書いたけど、やっぱりキモイなぁ

ちなみに、一緒に悩んでくれた先輩が、自分で今までに書いたscriptを読み返したら、全てwhileの中で参照していた、との事でした

# 無意識にやってたらしい。scope持つって知って驚いてた

# というか、その場にいた他の人も誰も知らなかったw

gdi++

試してみた。

…これはスゲェ

ただ、スレを見ると「重い、重い。でもFirefoxだと平気って書いてある」

たしかにFirefoxだと4倍綺麗にしても全然気にならない。TeraPadも同じく。

だけどPuTTYとかCottonだとかな〜り重くて実用には耐えない感じ。Becky!は重いなりにもまぁ使えるかな、という感じ。何が違うんだろうなぁ

あとは、.txtとかを開いたときに開かれるエディタにhookさせる方法が分からず。これが出来るとうれしいなぁ

本日のツッコミ(全3件) [ツッコミを入れる]
# UmaShika (2006年9月24日(日) 12:55)

whileループの done の前に ps 入れて、実行して味噌。<br>からくりの端緒が見つかると思われるので。<br>#変なことを覚えるより、落とし穴に陥らない処理の仕方を考えたほうがよいとおもわれ。

# smbd (2006年9月25日(月) 22:56)

パイプでつないでるからsub shellになってしまうのね…納得<br>whileだけならscopeを持たないようで。(実装依存らしいけれど)

# kitaj (2006年9月26日(火) 01:25)

hoge() {<br> local r=""<br> while read foo; do<br> ...<br> done<br> echo $r<br>}<br>みたいなのを用意しといて<br>uga=$(echo "guhehe"|hoge)<br>なんてのをよくやるよ.<br><br>でも,素直にmktempで一時ファイル作った方が楽なときもあるよね.

./20060923.html#c">ツッコミを入れる]



«前の日記(2006年9月11日(月)) 最新 次の日記(2006年10月10日(火))»