[表示 : 全て 最新50 1-99 101- 201- 301- 401- 2chのread.cgiへ]
Update time : 05/09 22:57 / Filesize : 109 KB / Number-of Response : 480
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

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



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/

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を発行するのはパイプさん?






[ 新着レスの取得/表示 (agate) ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<109KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef