- 1 名前:名無しさん@お腹いっぱい。 [2008/05/20(火) 20:58:04 ]
- シェルスクリプトの総合スレです。
スクリプトのお勉強・自慢・腕試しなどにどうぞ。 まずは注意点、リンク、地鎮祭など(>>1-6くらい)をご覧ください。 □お約束 ・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。 Linuxユーザは/bin/shの正体がbashなので特に注意。 ・csh/tcshのシェルスクリプトは推奨されません。 (理由は「csh-whynot」でググれ) ・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。 manや参考リンクを見ましょう。 aproposないしはman -kでそれらしい単語による簡単な検索もできます。 ・シェルスクリプトのことをシェルってゆーな ・シェルで使えるワイルドカード等は正規表現ではありません。 正規表現の話題はスレ違い(正規表現スレへ) □初心者へのアドバイス: ・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも RubyやPerlの方が適した仕事には素直にそちらを使いましょう。 ・知らないコマンドが出てきたらmanを引きましょう。 ・思い通りに動かないときは、まずは sh -x でトレースしましょう。 シェルスクリプト総合 その10 pc11.2ch.net/test/read.cgi/unix/1202725267/
- 401 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/06/29(日) 21:24:06 ]
- sed -n 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/p'
- 402 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/06/29(日) 21:44:44 ]
- >>401
>>397 の指摘で失格
- 403 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/06/30(月) 01:27:41 ]
- よほどパフォーマンスに差がありでもしないかぎり、
書き易く読み易いようにすればいい。
- 404 名前:388 mailto:sage [2008/06/30(月) 01:39:46 ]
- みなさま色々とありがとうございました。
>>398 ちゃんと処理できるみたいですし、このスレでも良い評価なので これを使ってあげようかと思います。感謝してください。 この処理は、あるとても重要な国家プロジェクトで使用されます。 コメントで Powered by 398 と入れておきますね。
- 405 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/06/30(月) 01:59:48 ]
- なわけねーだろ
- 406 名前:名無しさん@お腹いっぱい。 [2008/07/02(水) 17:31:55 ]
- 誰かお願いします。
wk=f 配列にa b c d とそれぞれ入ってるとして ループでぐるぐるっと、wkと一致するものを探したいんですが、 もし一致するものが無かった場合の終了条件って、どうしたらいいですか。
- 407 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/02(水) 17:41:16 ]
- 日本語でおk
- 408 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/02(水) 17:42:11 ]
- 純正シェルに配列はない。配列に相当する別の処理をしているなら、
その処理方法を明示して質問し直した方がいい。
- 409 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/02(水) 17:43:56 ]
- >>406
多少エスパーして回答。 ループにwhileを使うんじゃなくて、 forで配列の要素分ループすれば、たとえ一致するものが無かった場合でも ループはちゃんと終了するから問題なし。
- 410 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/02(水) 17:48:51 ]
- ループの返り値ってことなら、breakとかを使わん限り最後のコマンドの実行結果になるから、
ループの最後にfalseを置いとけばいいんじゃないかね。 成功した場合はbreakで抜ける、ということならば、だけど。
- 411 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/02(水) 17:51:11 ]
- >>406 の日本誤訳:
以下のようなシェルを発行しようとしたのですが、 もし一致するものが無かった場合、うまくいきません。 どうすればいいですか? #!/bin/bash wk=f array=(a b c d e) i=0 while [ ${array[i]} != $wk ]; do ((i++)) done
- 412 名前:名無しさん@お腹いっぱい。 [2008/07/02(水) 17:57:26 ]
- 皆様あざーっす!
とりあえず今、KSHって何だって事から教わりました。怒鳴り含み。 ちょっと参考にして、考えます。皆暖かいアドバイスども!
- 413 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/02(水) 17:59:21 ]
- 突然何を言い出すんだ?
- 414 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/02(水) 18:08:51 ]
- キチガイ警報
- 415 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/02(水) 22:22:49 ]
- 作成したいファイル名が書かれたtxtのリストから、
ファイルを作成するにはどうすればよいでしょうか? たとえばテキストの中身に、 hoge foo bar とあったとして、 hogeとfooとbarというファイルを作成したいのです。
- 416 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/02(水) 22:34:11 ]
- >>415
touch $(cat txt)
- 417 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/02(水) 22:46:52 ]
- >>416
なんでこれでできるのかわからないですができました ありがとうございます
- 418 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 02:22:28 ]
- >>416 それだと大量だった場合に引数溢れのエラーにならないかな?
- 419 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 02:25:14 ]
- >>418
じゃあ cat txt | xargs touch
- 420 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 03:05:13 ]
- cat txt|while read FNAME
do touch $FNAME done べたですがw
- 421 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 07:17:23 ]
- >>419
xargsは使っちゃいけないコマンド。 >>420 それだと catが無駄。touchがむだ。 while read FNAME do > "$FNAME" done < txt
- 422 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 07:19:13 ]
- >>416
bash依存、失格。 > `cat txt`
- 423 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 07:23:31 ]
- >>421
415とは関係ないんだけど パイプでxargsに渡すときに空白をエスケープするにはどうすればいいの 例えばfindで見つけたパスに空白が含まれてた場合とか
- 424 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 07:49:19 ]
- >>423 テンプレ>>6
- 425 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 07:55:01 ]
- >>424
テンプレにあったとは すいませんでした
- 426 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 08:02:10 ]
- テンプレにはないが、find -print0 | xargs -0 するんじゃなくて、
find -exec + するのが今後のお勧めだな。-exec の後ろ、\; じゃなくて + ね。 これでxargsは完全に不要!
- 427 名前:名無しさん@お腹いっぱい。 [2008/07/03(木) 11:31:21 ]
- 質問です。
case文でwhile文を使用する時 case "$a" in "a.c") while[ $flag = false || $i -ne 10 ] ; do 処理1 done の時、doneの跡に;;でおkですか?
- 428 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 11:56:24 ]
- >>421がFAだけど、敢えてxargs -0で。
cat list.txt | perl -ane '{ chop; printf("%s%c", $_, '\0'); }' | xargs -0 touch
- 429 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 11:57:44 ]
- >>426
この+でappendって、最近のfindはどれにもあるの?
- 430 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 11:58:53 ]
- 純正findにないから使っちゃだめ
- 431 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 12:18:04 ]
- >>430
純正findにもあるんだなぁ、+ が。よって find -exec + で FA。
- 432 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 12:31:00 ]
- xargs を使っちゃいけない理由キボンヌ
便利だし早いからコマンドラインで結構使うんですが・・・
- 433 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 12:31:12 ]
- 純正find にないのは -print0 の方ですね。
- 434 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 12:40:55 ]
- 純正なんとかっていう意味の曖昧な言い方は止めろ
今はPOSIX準拠かどうかの話をしてるようだが、 純正シェルは古い/bin/shの話だったりでわからん
- 435 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 12:45:23 ]
- >>432
$ printf "This is\na test.\n" This is a test. $ printf "This is\na test.\n" | xargs -n 1 echo This is a test. $ printf "This is\na test.\n" | perl -ane 'chop; printf("%s%c", $_, '\0');' | xargs -0 -n 1 echo This is a test. $
- 436 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 12:46:31 ]
- & >>6 (>>424は読んだ?)
- 437 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 13:03:20 ]
- >>435
なるほど、理解しますた。分かってれば使えないことはないですな。
- 438 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 16:40:13 ]
- まぁ実験して動いたらそれでまずOK。
でその後にリファイン(リファクタリング?) これが大事。
- 439 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 17:28:35 ]
- >>6
> (スペースなどを含むファイル名を正しく処理するため、 > findは -print0、xargsは -0オプションを常に付けることを推奨 > ただし、Solarisでは未対応。どうするんだろ?) $ cat print0 #! /bin/sh while read x; do printf "%s\0" "$x" done $ find 〜 | print0 | xargs -0 〜 でいいんじゃね? # printfは許してね。
- 440 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 18:16:12 ]
- >>439
いや、だから、Solarisでも find dir -exec hoge + が使えるんだよ。 よってprint0云々は一切不要。
- 441 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 18:21:41 ]
- >>439
ファイル名に \ が含まれていた場合、readが誤動作する(違うファイル名とみなされる) Solarisの xargsには -0 オプションがない。 で、>>440 の方法で解決。
- 442 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 18:58:56 ]
- トレースしてみた。
strace -f find /tmp -exec file {} + 2>&1 execve("/usr/bin/file", ["file"..., "/tmp"..., "/tmp/.ICE-unix"..., "/tmp/mysql.sock" ..., おお、すげぇ。ちゃんと引数まとめて実行してるね。 strace -f find /tmp -exec file {} \; 2>&1 execve("/usr/bin/file", ["file"..., "/tmp"...], [/* 21 vars */]) = 0 execve("/usr/bin/file", ["file"..., "/tmp/.ICE-unix"...], [/* 21 vars */]) = 0 execve("/usr/bin/file", ["file"..., "/tmp/mysql.sock"...], [/* 21 vars */]) = 0 こっちは1個ずつ実行するから大量だとクソ遅い。 勉強になりまつた。
- 443 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 19:55:30 ]
- やっぱ速さってみんな気になるん?
しっかりきっちり動けば、速度は問題ないって思ってる俺は未熟? いかにもベターってのはやらないけどー。
- 444 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 20:03:16 ]
- テクいことして読み難くなるなら多少遅くても分かりやすく書く
- 445 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 20:08:46 ]
- >>442
straceって、、Linuxかよw
- 446 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/03(木) 23:57:40 ]
- >>443
必要な時に必要なことをやる。当たり前のこと。 後の話はマ板でやって。
- 447 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/04(金) 01:32:47 ]
- cronで毎日回しているプログラムの処理時間が
16時間越えたらちょっと悩む
- 448 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/04(金) 08:05:24 ]
- kshでユーザIDのリストを計表にして印刷したいんだけど
こんなの作った人いますか? どこかにサンプルありませんかね。OSは、AIX5.3です。
- 449 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/04(金) 08:27:34 ]
- >>448
計表の正確なところがわからんが、 while read user pass uid rest; do echo $uid $user ; done < /etc/passwd ってことか? あと、必要なら sort -n をかましてね。 kshじゃなくて純正シェルでできるよ。
- 450 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/04(金) 08:29:48 ]
- >>448
あ、IFS設定抜けてた。 IFS=:; while read user pass uid rest; do echo $uid $user ; done < /etc/passwd
- 451 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/04(金) 08:42:50 ]
- ksh -c lpr < /etc/passwd
- 452 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/04(金) 11:13:09 ]
- FreeBSD 付属の wc は空白文字でパディングして結果を返すようです。
wc -l $file | sed "s/ /_/g" _____340_/usr/bin/g++ Linux では次のようにして 340 という値を得ていたのですが、 FreeBSD では空白文字が出力されてしまいます。 wc -l $file | cut -f1 -d" " FreeBSD 版 wc ではどうすればいいでしょう。 ltrim() みたいなものがありますかね。 それともいったん sh の変数に代入する? それとも wc や cut には未知のオプションがある? cut なんていう頑ななコマンドは使わないで、 sed 's/^ *\([0-9]*\) .*$/\1/' しろ? お前 awk '{ print $1 }' も書けないのか? bash をよく使うので、依存しているところがあったらごめんなさい。 awk はほとんど馴染みがありません。というか、 何かにつけて不遇の cut を使ってあげたい気持ちがあります…。
- 453 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/04(金) 11:15:19 ]
- >>452
echo `wc -l < $file`
- 454 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/04(金) 11:28:33 ]
- >>452
長文で cutを力説してるのに、 >>453 で cutすら必要ないというオチにワロタ wc で、引数じゃなくて標準入力の場合はもともとファイル名が出ないので cutとかで切る必要ないのと、スペースを取り除くにはシェルの ` ` を使うってことね。
- 455 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/04(金) 11:33:53 ]
- > それともいったん sh の変数に代入する?
質問者が用意した選択肢を誇らしげに答える>>453-454が憐れ。
- 456 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/04(金) 11:38:03 ]
- 空白文字のパディング方式に、
暗黙の仮定を置いてまでcutにこだわる意味が全くわからん。 仕様の特殊化しても嬉しくない。
- 457 名前:452 mailto:sage [2008/07/04(金) 11:38:04 ]
- いやいや
> wc で、引数じゃなくて標準入力の場合はもともとファイル名が出ないので 役に立ちました! 確かに笑った。
- 458 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/04(金) 11:38:44 ]
- >>455
おまえ、シェルスクリプト書いたことないだろ? >>453 では一切「sh の変数に代入」は行なっていないがww
- 459 名前:452 mailto:sage [2008/07/04(金) 11:50:48 ]
- >>456
いやいや、そうなんですよ。 cut ってつまり結局 他のコマンドと組み合わせるには中途半端なツールなんですよ。 単純でそれなりに覚えやすく、見込みのあるヤツだと思ってたんですが… awk や bash は区切り文字を変えるだけでも結構タイプする印象が。 いや、変にこだわってごめんなさい。
- 460 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/04(金) 12:06:44 ]
- つ awk -F:
- 461 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/04(金) 15:50:34 ]
- cut はデリミタの連続を指定できれば使える君に化けるんだがな。
- 462 名前:名無しさん@お腹いっぱい。 [2008/07/08(火) 07:58:27 ]
- シェルスクリプトがCなどのプログラムより重い理由をうまく説明したいんですが
- 463 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/08(火) 08:00:46 ]
- >>462
インタプリタ型言語だから。 (fork/execが遅いと言うだけが理由ではない。 内部コマンドだけを使ってもCよりも遅いから)
- 464 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/08(火) 10:52:14 ]
- でも一番のボトルネックは fork, exec だと思うぞ
- 465 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/08(火) 11:29:48 ]
- プロファイルしてみると分かるが、文字列処理も結構コストが高い。
stat(2)せずにls -lしてからパターンマッチなど。 shは文字列がグルーになっているから。
- 466 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/08(火) 14:57:58 ]
- パイプとかバッククォートとかガンガン使うから、
それだけでシステムコール連発になっちゃうもんね。 文字列処理なのに write(2) とか使うわけだw
- 467 名前:名無しさん@お腹いっぱい。 [2008/07/08(火) 21:54:18 ]
- レスありがとう
ちなみにパイプでコマンドつないだ場合って一つ一つ最後まで処理して次のコマンドに移るであってますかね?
- 468 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/08(火) 21:56:21 ]
- >>467
全然合ってない。それは MS-DOSのニセパイプの動作。
- 469 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/08(火) 22:14:44 ]
- >>468
詳しくおしえてください・・・
- 470 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/08(火) 22:21:27 ]
- >>469 シェル pipe dup2 とかで検索してみ。
- 471 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/08(火) 22:50:12 ]
- そんな検索語じゃわかるわけないだろ。
pipe(2)だって無限にバッファがあって、 入口が閉じるまで出口から出て来ない仕様になってる可能性だってあるわけで。
- 472 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/08(火) 23:22:32 ]
- 無限の記憶装置は存在しないのでそんな可能性はゼロだな。
- 473 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/08(火) 23:25:31 ]
- MS-DOSのパイプ仕様を実装することも不可能だな。
- 474 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/08(火) 23:36:10 ]
- コマンド1 | コマンド2
本来のパイプだと、 コマンド1 の標準出力 = コマンド2の標準入力 になるような操作(dupとか)が裏で行われる。 コマンド1と2は同時に実行される。一時ファイルを介さない。 嘘パイプの場合は、 コマンド1 > 一時ファイル コマンド2 < 一時ファイル 削除 一時ファイル なだけ。
- 475 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/08(火) 23:57:58 ]
- 例えば
cat ばかでかいファイル | head -1 だとcatもheadも同時に起動してheadはcat の出力が1行分でたらそれを出力します そのときcatの処理が途中だったらどうなるんですか?
- 476 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/09(水) 00:11:11 ]
- やってみろよ
- 477 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/09(水) 00:50:57 ]
- >>475
バッファってしってるか?
- 478 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/09(水) 01:22:00 ]
- >>475
catがwrite(2)を呼び出したときにheadが終了している(パイプが閉じている)とSIGPIPEくらって終了。
- 479 名前:名無しさん@お腹いっぱい。 mailto:sage [2008/07/09(水) 02:16:51 ]
- そのshigpipeを発行するのはパイプさん?
|

|