トップページunix
1001コメント297KB

シェルスクリプト総合 その22

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2013/11/01(金) 07:58:50.52
シェルスクリプトの総合スレです。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
 Linuxユーザは/bin/shの正体がbashまたはdashなので特に注意。
 FreeBSDユーザは/bin/shの正体がashなので注意。
 v7 shに一番近くて、現役のshは、OpenSolaris由来のheirloom sh。
  http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/sh/
  http://heirloom.sourceforge.net/sh.html
・csh/tcshのシェルスクリプトは推奨されません。
 (理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
 manや参考リンクを見ましょう。
 aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルで使えるワイルドカード等は正規表現ではありません。
 正規表現の話題はスレ違い(正規表現スレへ)
・シェルスクリプトのことをシェルってゆーな
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
 awkまたはperlの方が適した処理にはそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
□回答者への注意事項:
・シェルスクリプトでの処理方法を質問しているのに、よくわからずに
 「そういうのはperl使いましょう」と回答するのはやめましょう。
 安易にperlに逃げずにシェルスクリプトで処理するのが頭のいいやり方。
前スレ
シェルスクリプト総合 その21
http://toro.2ch.net/test/read.cgi/unix/1352973453/
0002名無しさん@お腹いっぱい。2013/11/03(日) 03:04:59.12
おつ
0003名無しさん@お腹いっぱい。2013/11/03(日) 08:20:00.06
bash なら exponent は ** なのにな
0004名無しさん@お腹いっぱい。2013/11/04(月) 13:06:48.63
case文を抜け出す方法はbashには無かったけど
ほかのシェルでcase文から抜け出す方法はある?
0005名無しさん@お腹いっぱい。2013/11/04(月) 15:04:59.50
;;でcaseから抜けるけど
0006名無しさん@お腹いっぱい。2013/11/05(火) 11:03:36.55
if [ $? -eq 0 ]; then

みんな、$? は""で囲う派? 囲わない派?
0007名無しさん@お腹いっぱい。2013/11/05(火) 18:10:47.33
普段は囲まないけど、誰かの書いたのをいじるときはそれに合わせるよ派
0008名無しさん@お腹いっぱい。2013/11/06(水) 07:06:35.01
数値なので囲わない派
0009名無しさん@お腹いっぱい。2013/11/06(水) 08:25:01.88
$前に0付ける派
0010名無しさん@お腹いっぱい。2013/11/06(水) 11:17:00.72
$の前に0つけるのってファイナルビューティ醸してるな。
この発送はなかった。
0011名無しさん@お腹いっぱい。2013/11/08(金) 15:58:55.00
>>9
8進数になることない?
0012名無しさん@お腹いっぱい。2013/11/08(金) 16:21:43.15
>>11
あるねw
0013名無しさん@お腹いっぱい。2013/11/08(金) 16:57:46.84
$ test 12 -eq 12; echo $?
0
$ test 012 -eq 12; echo $?
0
0014名無しさん@お腹いっぱい。2013/11/08(金) 17:49:27.80
>>13
あ、使ってる関数は自動変換するけど、10進数限定にもできて、testは限定されてた。
だからやっぱりないw
0015名無しさん@お腹いっぱい。2013/11/09(土) 13:58:50.12
マイナス
"負数"が返ってきたらアウトだな

と思ったけど実行結果は必ず0か自然数なので問題なかった
0016名無しさん@お腹いっぱい。2013/11/10(日) 17:23:11.15
あるファイルが、実行可能な設定ファイルであることを
チェックして保証したいんだけど、なんかいい方法ある?

手抜きなんかしないで、ひとつひとつちゃんと
HOGE="PIYO"
みたいなフォーマットにのっとってることを
文法チェックして確認しないとだめ?
0017名無しさん@お腹いっぱい。2013/11/10(日) 19:40:09.82
実行可能って、エラーを発生させることなくパース可能という意味?
任意の書式だと困難だと思うけど。
0018名無しさん@お腹いっぱい。2013/11/11(月) 01:57:30.15
>>16
何の設定ファイル?
0019名無しさん@お腹いっぱい。2013/11/11(月) 09:45:35.56
それは秘密
0020名無しさん@お腹いっぱい。2013/11/11(月) 10:08:05.71
それがわからないと答えにくい。
0021名無しさん@お腹いっぱい。2013/11/11(月) 15:43:09.06
そのファイルでどこまでの記述を許すかによるんじゃない?
a="b" の範囲内ならgrepでできるかもしれない。
a=${hoge:=piyo} とかも許すなら、俺しらね。
さらにシェルで書けることならなんでもOKとするなら、
本気でパーズしなきゃだめだろ。
0022名無しさん@お腹いっぱい。2013/11/11(月) 19:30:27.56
シンタックスが正しくてもセマンティクスが正しくなければ
「実行可能」ではないのでは?
0023名無しさん@お腹いっぱい。2013/11/11(月) 20:16:49.22
16はもう来ないのか?
0024名無しさん@お腹いっぱい。2013/11/12(火) 21:21:47.34
bashがデカ過ぎる…。そして重過ぎる…。
0025名無しさん@お腹いっぱい。2013/11/13(水) 12:42:19.69
>>17
そうだね

>>21
設定ファイルとして使いたいけど実装は面倒なので実行で済ませたい
って横着な話が起点なので、いい方法がなければ自力でチェックします。

bash -r とか使えるかなと思ったけど無意味っぽかった
0026名無しさん@お腹いっぱい。2013/11/13(水) 13:08:08.67
ならスクリプトとして完全なチェックは必要ないよね。
自力でもそんなに難しくないんでは。
0027名無しさん@お腹いっぱい。2013/11/20(水) 19:52:35.18
一定時間、何度か繰り返しコマンドを実行したくて、

for i in `seq 1 10`
do
 何かのコマンド
 sleep 1h
done
echo "finished" | write username

といったスクリプトを書いているのですが、このやり方だと
最後にコマンドを実行してから一時間、無駄に sleep してしまいます。
最後の sleep だけ実行しない方法はないでしょうか。
0028名無しさん@お腹いっぱい。2013/11/20(水) 19:58:50.00
再編集の時が恐いけど
変数 i<=9 のときにsleep 1h

i/=10の時に sleep 1h
0029名無しさん@お腹いっぱい。2013/11/20(水) 20:00:40.20
>>27

i=10
while
 何かのコマンド
 ((--i)) &amp;&amp; sleep 1h
do :; done
echo "finished" | write username
0030272013/11/20(水) 20:07:56.43
おお! 素早い回答、ありがとうございます。
ですが、たびたびすいません。

実際に使っているスクリプトだと、ループの実行回数が不定な場合があるのです。
(行数が特定できないファイルからの読み込みとか)
最後のループでは sleep しない、という手段はあるでしょうか。
0031272013/11/20(水) 20:19:58.58
よく考えたらファイルからの読み込みも終了判定できますね。
何とか工夫すれば、判定できないループってないかも……。
どうもお騒がせしました。
0032名無しさん@お腹いっぱい。2013/11/20(水) 23:30:36.92
>>29
((--i)) でiが0になる時、返り値1なんだ。
iが負の値になる時でも返り値0なのに、0になる時だけ特別なんですね。
0033名無しさん@お腹いっぱい。2013/11/21(木) 00:11:48.01
If the value of the expression is non-zero, the
return status is 0; otherwise the return status is 1.
0034教えてくだしあ2013/11/21(木) 23:17:15.63
pingを打って 成功⇒次のping 失敗⇒EXIT
もっかい別のとこにping 成功⇒ログ出力 失敗⇒コマンド実行
こんな感じのスクリプト作りたいんだけど
pingの結果って$?に入るんだよね
これって複数あった場合どうすれば良いの?
0035名無しさん@お腹いっぱい。2013/11/21(木) 23:18:56.88
>>34
どういうこと?
0036名無しさん@お腹いっぱい。2013/11/21(木) 23:21:59.47
>>34
直前のコマンドの結果で毎回 $? が上書きされるだけ。
0037342013/11/21(木) 23:26:22.05
わかり難くてすません

1.ping打つ 成功⇒2へ 失敗⇒終了
 ↑ココの$?
2.ping打つ 成功⇒ログ書き込み 失敗⇒コマンド実行
 ↑ココの$?

で結果を分けて処理しようと考えてます。
根本的に考え方が違うなら考えを改めるよ
0038342013/11/21(木) 23:28:11.31
>>36 それが知りたかった エスパーありがとう
0039名無しさん@お腹いっぱい。2013/11/21(木) 23:29:46.92
>>38
>>36 の回答は理解できないの?

hoge=$? でコピーしておいてもいいし
0040342013/11/21(木) 23:47:57.56
期待通り動いたわ ありがとな
ちなこれって、ここの住人はどんな感じで書くん?
ping -c 3 192.168.43.1 >/dev/null
PING1=$?
if
[ ${PING1} -eq "0" ];then
ping -c 1 192.168.254.100 >/dev/null
PING2=$?
if
[ ${PING2} -eq "0" ];then
echo Status=OK
exit
else
/etc/script/wol 192.168.254.255 10:78:D2:4B:D6:55
echo WAKE-ON-LAN
fi
else
echo NoThanks
exit
0041名無しさん@お腹いっぱい。2013/11/22(金) 00:01:34.93
if ping -c 3 192.168.43.1 >/dev/null; then
 if ping -c 1 192.168.254.100 >/dev/null; then
  echo Status=OK
 else
  /etc/script/wol 192.168.254.255 10:78:D2:4B:D6:55
  echo WAKE-ON-LAN
 fi
else
 echo NoThanks
fi

全角空白は置換してくれ。
0042342013/11/22(金) 00:08:55.90
おいおい条件要らないとかマジかよ
意外とスクリプト面白いな
0043名無しさん@お腹いっぱい。2013/11/22(金) 00:09:42.94
条件要らない?
どういうこと?
0044名無しさん@お腹いっぱい。2013/11/22(金) 01:55:31.53
ifが変数に入れなくてもそのまま戻り値でいけるってとこじゃね?
0045名無しさん@お腹いっぱい。2013/11/22(金) 08:48:23.24
ifに条件は要るだろ。
0046名無しさん@お腹いっぱい。2013/11/22(金) 09:22:12.61
ping -c 3 192.168.43.1 >/dev/null && { ping -c 1 192.168.254.100 >/dev/null && echo Status=OK || { /etc/script/wol 192.168.254.255 10:78:D2:4B:D6:55; echo WAKE-ON-LAN; }; } || echo NoThanks
0047名無しさん@お腹いっぱい。2013/11/22(金) 22:29:53.59
if使わない方法もあるのね。なかなか勉強になるぜ
>>43 [ ${PING1} -eq "0" ];これってpingの変数が0だったらって条件じゃないの?
1とか他の値だったら条件に合わないよね?
でも>>41のを見るとそんな条件なく成功=次へって感じに見えるけど
何処に条件が書いてあるん?
分かり易く教えてくだしあ
0048名無しさん@お腹いっぱい。2013/11/22(金) 22:46:39.23
if は、条件がどうこうじゃなく、コマンドの戻り値で判断する文法。
[ ... ] の [ は、ifの文法じゃなくて [ という名前のコマンド。
0049名無しさん@お腹いっぱい。2013/11/23(土) 00:18:20.98
testコマンドじゃなかったか? => []
0050名無しさん@お腹いっぱい。2013/11/23(土) 00:33:47.23
test と [ は同じ物。
コピーかリンク。
] は関係ない。
0051名無しさん@お腹いっぱい。2013/11/23(土) 00:41:18.75
test を [ という名前で起動するときは、
最後に ] という引数を要求するようになっている、という仕組み。
0052名無しさん@お腹いっぱい。2013/11/23(土) 01:22:07.55
ping文が条件じゃん。
0053名無しさん@お腹いっぱい。2013/11/23(土) 19:24:30.28
f=
if [ -f "$f" ]; then
echo "ファイル$fはある"
else
echo "ファイル$fはない"
fi

を実行すると、
ファイルはない

f=
if [ -f $f ]; then
echo "ファイル$fはある"
else
echo "ファイル$fはない"
fi

を実行すると、
ファイルはある

"$f" でないと「ある」になるんですが、
そんなファイルはないのに、なぜなんでしょう?
0054名無しさん@お腹いっぱい。2013/11/23(土) 19:33:31.33
[ -f $f ] は [ -f ] と同じ意味になって、
[ コマンドがそれを真とみなすから。
0055名無しさん@お腹いっぱい。2013/11/23(土) 19:34:30.39
[ -f "" ] && echo hoge

[ -f ] && echo hoge
ってことだな。

>>54
なぜ真とみなされるのか、という疑問では。
0056名無しさん@お腹いっぱい。2013/11/23(土) 19:39:50.36
-f が単なる文字列として解釈されているのでは

`-n STRING'
`STRING'
True if the length of STRING is nonzero.
0057名無しさん@お腹いっぱい。2013/11/23(土) 19:39:51.89
マニュアルには -f file の場合しかないんで、-f だけだと未定義。
ということは、真になろうが偽になろうが利用者は文句を言えない。
最初の実装上たまたま真にしたんじゃね?
で、その実装がそのまま引き継がれていると。

以上、想像。
0058名無しさん@お腹いっぱい。2013/11/23(土) 19:41:30.39
>>56
あぁ、それが合理的だな
0059532013/11/23(土) 19:57:40.35
さすがこのスレは物知りが多いですね

$ test hoge
$ echo $?
0

だから

$ test -f
$ echo $?
0

も同じってことですか なるほど
しかし、わかりにくいってか間違いやすいなー
■ このスレッドは過去ログ倉庫に格納されています