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

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

レス数が1000を超えています。これ以上書き込みはできません。
0001名無しさん@お腹いっぱい。2007/08/15(水) 07:25:02
シェルスクリプトの総合スレです。
スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>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 でトレースしましょう。

前スレ
シェルスクリプト総合 その8
http://pc11.2ch.net/test/read.cgi/unix/1171517324/
0933名無しさん@お腹いっぱい。2008/02/11(月) 18:04:11
確かに無駄に毎行処理するのは(>>914は最後のみ実行だが、それまでも内部処理される)よろしくないな。
>>914 最適な解を望む。 最適な解だぞ。
0934名無しさん@お腹いっぱい。2008/02/11(月) 18:07:05
>>932
だから、awkを使ってっていってるのに、
なんで awk側でできる cat -n や tail -1 相当の処理を
awk側でやらないのかってこと。

>>930 の最後の行で言ってる、「最後までawkを使わずに処理するべき」ってのは、
「cat -n | tail -1」を使う以上は、ってこと。
で、それだと「awkを使う」という質問に適合しないから、
>>911 は解にならないと言いたいわけ。
0935名無しさん@お腹いっぱい。2008/02/11(月) 18:08:05
perl -lne 'END{print$.}' < file
かな。
0936名無しさん@お腹いっぱい。2008/02/11(月) 18:09:37
>>934
それだとお前の最適って言う言葉も最適ではないから解ではないな。
0937名無しさん@お腹いっぱい。2008/02/11(月) 18:14:55
元質問者は >>922 で、>>914 を使って解決したんだからそれでいいじゃん。

で、>>920 で言ってるように、本当は wc -l を使いたかったけど、
それだと日本語環境で文字コードが解釈されてエラーになるのが問題なんだから、

>>923 が言うように、
LANG=C LC_ALL=C wc -l
が最適解だね。
0938名無しさん@お腹いっぱい。2008/02/11(月) 18:18:55
tmp]$ time perl -lne 'END{print$.}' < tmp
89232

real 0m0.359s
user 0m0.327s
sys 0m0.011s
tmp]$ time perl -e 'while(<>){} print "$.\n"' tmp
89232

real 0m0.273s
user 0m0.236s
sys 0m0.010s

tmp]$ time awk 'END{print NR}' tmp
89232

real 0m0.150s
user 0m0.126s
sys 0m0.009s

tmp]$ perlcc -B tmp.pl; time ./a.out tmp
89232

real 0m0.286s
user 0m0.263s
sys 0m0.000s

やっぱりawkが早いな。
0939名無しさん@お腹いっぱい。2008/02/11(月) 18:19:55
>>937
awk, Perlを使っての解がしりたかったみたいだから、wcは最適じゃないな。
09409382008/02/11(月) 18:20:42
っていうか、バイトコンパイルしたら遅くなっちった。
0941名無しさん@お腹いっぱい。2008/02/11(月) 18:30:05
>>939
>>920 欲嫁。質問者はwc使いたかったけど使えなかったから仕方なくawkまたはperlで
ということだから、>>923 のwcが最適だね。
0942名無しさん@お腹いっぱい。2008/02/11(月) 18:35:26
コントロールコードが入ってたりしてwcが使えないのが原因だったらどうするの?
勝手に想像するのは良くないよ。
>>924欲嫁
0943名無しさん@お腹いっぱい。2008/02/11(月) 18:37:51
>>942
> コントロールコードが入ってたりしてwcが使えないのが原因だったらどうするの?

そんなのありえるの? 具体的には?
0944名無しさん@お腹いっぱい。2008/02/11(月) 18:38:27
>>942
コントロールコードが入っていても LANG=C なら wcは無問題。
実際に試してから言おうね。
0945名無しさん@お腹いっぱい。2008/02/11(月) 18:41:01
>>944
全てのコントロールコードで試したの?
そのファイルをくれないかな。
0946名無しさん@お腹いっぱい。2008/02/11(月) 18:44:45
>>945
墓穴ほってるよww

そんなの、たとえば
dd if=/dev/random bs=1024k count=1 | LANG=C wc -l

で検証できる。ファイル用意する必要なし。
0947名無しさん@お腹いっぱい。2008/02/11(月) 18:47:29
コントロールコードなら有限だから楽勝だな。
09489452008/02/11(月) 18:47:55
俺は全てのコントロールコードで試したとは言っていないが?
君が、
> 実際に試してから言おうね。
って言ったんじゃないの?
randomで出したところで、全てのコントロールコードは試してないよね。
実際に試してないのに言っちゃったの?
09499452008/02/11(月) 18:49:46
>>946
あと、それはどうやって正確に行数を数えてることを実証するの?
どこかに書き出して、自分で数えたりしてるの?
0950名無しさん@お腹いっぱい。2008/02/11(月) 18:51:27
意外に最初想像したよりもおもしろい展開になったな
0951名無しさん@お腹いっぱい。2008/02/11(月) 18:52:24
>>948
コントロールコードって、全部で32個(DELも入れると33個か?)だけって知ってる?
09529452008/02/11(月) 18:52:59
tmp]$ dd if=/dev/random bs=1024k count=1 > tmp_r

tmp]$ cat tmp_r | LANG=C wc -l
0
tmp]$ cat tmp_r | perl -e 'while(<>){} print "$.\n"'
1
tmp]$ cat tmp_r | awk 'END{print NR}'
1
tmp]$ cat tmp_r | perl -lne 'END{print$.}'
1


ものすごい影響されてるが…。
0953名無しさん@お腹いっぱい。2008/02/11(月) 18:53:37
以降、>>945 がいつまで自分の無知をさらけだすか見守りたいと思います。
0954名無しさん@お腹いっぱい。2008/02/11(月) 18:55:43
>>952
ワロタwwwwww
>>951は自分の発言すら試してなかったのか?w
それともたまたまうまくいっただけか
0955名無しさん@お腹いっぱい。2008/02/11(月) 19:00:40
>>952 では別の問題が発生してるみたいだね。
/dev/randomじゃなくて /dev/urandomでやるべき。
/dev/randomを ddで吸い出すと、十分なエントロピーがなくて
ほとんどがゼロで埋まってるものと思われ。

それとは別に、wc -lでは、最後の改行がない行を数えないが、
awk 'END{print NR}'では数えるから、行数が1ずれる。

その点は、>>945 が最初指摘していたコントロールコードの問題とは違うので、
勘違いしないように。
0956名無しさん@お腹いっぱい。2008/02/11(月) 19:04:10
>>952
だいたい、1MBも乱数で取ったのに '\n' が1つしかない時点で
その実験自体がおかしいことに気づけww 乱数になってない。
0957名無しさん@お腹いっぱい。2008/02/11(月) 19:06:04
952の人気はすばらしい
0958名無しさん@お腹いっぱい。2008/02/11(月) 19:06:49
乱数なんだから1個でどこがおかしいんだよ。
しかもファイルがおかしいにしても、今回はwcが扱えないことはわかったでしょ。
0959名無しさん@お腹いっぱい。2008/02/11(月) 19:06:53
改行コード(\n) = 1行
ということなら、この場合やはり LANG=C wc -l の計数表示が正しいということになる。
awk 'END{print NR}' では、最後の不完全な行までカウントしてしまう。

そういう意味で、やはり LANG=C wc -l が最適ということになるな。
0960名無しさん@お腹いっぱい。2008/02/11(月) 19:09:54
実験してみた。

$ echo -n a > file
$ LANG=C wc -l < file
0
$ awk 'END{print NR}' < file
1

ということだ。LANG=C wc -l の方が正しいな。
0961名無しさん@お腹いっぱい。2008/02/11(月) 19:10:33
では、>>914は自信満々だったけど正しくなかったのか。
最適とか言ってたのに残念。
0962名無しさん@お腹いっぱい。2008/02/11(月) 19:12:19
>>959
違うだろ
改行がある限り2行
0963名無しさん@お腹いっぱい。2008/02/11(月) 19:13:10
>>961
>>914 は wcを使わないという時点では最適だろ。
で、あとでwcを使わなかった理由が質問者から示されたから、
それならLANG=Cでということで、wcが最適になっただけのこと。
0964名無しさん@お腹いっぱい。2008/02/11(月) 19:13:51
定義問題だな
wcのmanではああなっているから
0965名無しさん@お腹いっぱい。2008/02/11(月) 19:14:30
では、結局新しい情報がでてきてもそれに答えられなかった>>914は最適じゃないでしょ。
次々に新しい解を出すのが>>914の言う最適な解なんだから。
0966名無しさん@お腹いっぱい。2008/02/11(月) 19:15:26
最適最適って言ってるけどさ,最適ってどういうこと?タイプ数が最小なものってこと?
0967名無しさん@お腹いっぱい。2008/02/11(月) 19:15:50
>>914に聞いてくれ。
0968名無しさん@お腹いっぱい。2008/02/11(月) 19:16:20
いいからそろそろ次スレよろ
0969名無しさん@お腹いっぱい。2008/02/11(月) 19:18:13
じゃあ>>970が次スレを立てる
0970名無しさん@お腹いっぱい。2008/02/11(月) 19:19:33
立ててきます
0971名無しさん@お腹いっぱい。2008/02/11(月) 19:25:06
シェルスクリプト総合 その10
http://pc11.2ch.net/test/read.cgi/unix/1202725267/
0972名無しさん@お腹いっぱい。2008/02/11(月) 20:25:21
このスレでダメだという指摘が出来ないものが最適。
0973名無しさん@お腹いっぱい。2008/02/11(月) 21:55:14
なんかいいスレだな。wktk
0974名無しさん@お腹いっぱい。2008/02/11(月) 22:31:36
というか、awkはスレ違い。
シェルならシェルだけでやれ。
0975名無しさん@お腹いっぱい。2008/02/11(月) 22:52:08
シェルだけでやる場合の最適解

n=0; while read dummy; do ((n++)); done < file ; echo $n
0976名無しさん@お腹いっぱい。2008/02/11(月) 23:06:41
>>975
bash依存。失格。
0977名無しさん@お腹いっぱい。2008/02/11(月) 23:33:04
じゃあこれでどう?
シェルだけということで、exprすら使わないようにしたよ

set --; while read dummy; do set "$@" a; done < file ; echo $#
0978名無しさん@お腹いっぱい。2008/02/11(月) 23:46:18
>>977
set -- はシェル実装依存。shift $# の方が確実だな。
0979名無しさん@お腹いっぱい。2008/02/12(火) 00:10:10
/bin/sh
だけでできるようにしてくれや。
0980名無しさん@お腹いっぱい。2008/02/12(火) 01:22:43
祭りに乗り遅れた。。
0981名無しさん@お腹いっぱい。2008/02/12(火) 07:24:15
>>979
>>977 は /bin/shだけでできる。
0982名無しさん@お腹いっぱい。2008/02/12(火) 07:46:07
>>977の動作のしくみがわからない俺わろた
0983名無しさん@お腹いっぱい。2008/02/12(火) 21:26:24
読むたびに位置パラメータ(知らなければコマンドライン引数みたいなものと思え)
にaという文字を追加。
最後に位置パラメータの「個数」(=aを追加した回数=行数)を表示。

0984名無しさん@お腹いっぱい。2008/02/12(火) 21:50:09
>>977
行末に \ がある行があると計数ミスするなぁ
0985名無しさん@お腹いっぱい。2008/02/13(水) 16:33:50
というか、wc (オプションなし)だと確かに LANG=C以外の時エラーが出るが、
wc -l とか wc -c だと、そもそも単語に分ける必要ないから文字コードも見ないし、
LANG=C にする必要ないぞ。
wc -l オプション付けてるのに LANG=C が必要なのって、どこの wcコマンド?
0986名無しさん@お腹いっぱい。2008/02/14(木) 22:16:07
>>977
それ、1万行とか10万行とかあってもちゃんと動作するんだろうか?
というか、$#の上限ってどこかで決まってるんだろうか?
0987名無しさん@お腹いっぱい。2008/02/14(木) 22:25:48
とりあえず上限調べて、予想するとかソース読むとか
0988名無しさん@お腹いっぱい。2008/02/14(木) 22:32:48
ボーンでは9が上限
0989名無しさん@お腹いっぱい。2008/02/15(金) 02:42:56
${10}
0990名無しさん@お腹いっぱい。2008/02/15(金) 07:27:00
>>989
だからぁ、ボーンでは ${10} は使えないんだよ。
0991名無しさん@お腹いっぱい。2008/02/15(金) 08:19:41
>>989

$ /bin/sh
$ uname -sr
SunOS 5.10
$ echo ${10}
bad substitution


知らないくせに余計な突っ込みするなよw
0992名無しさん@お腹いっぱい。2008/02/15(金) 08:31:15
shiftしても引数を9個以上とれないってこと!?
0993名無しさん@お腹いっぱい。2008/02/15(金) 08:44:59
shiftすれば行けるだろ。${10}は行けないけど。
0994名無しさん@お腹いっぱい。2008/02/15(金) 22:14:21
ash 0.3.8で
while :; do
set -- "${@}" a
echo $#
done
の出力が15000越えるところまでは見た。
これ以上元祖に近いシェルは手元にないので勘弁。

別に$10とかに直接アクセスできる必要はないんだよな。

0995名無しさん@お腹いっぱい。2008/02/15(金) 22:39:28
たしかに$1から$9をとばして$10だけが必要になる場面が想像できない
俺は極端には$1とshiftだけでもやっていけるな
0996名無しさん@お腹いっぱい。2008/02/15(金) 23:04:11
位置パラメータをコマンド引数として解釈する場合は ${10}とか要らないが、
set を配列代わりに使う用法では、${10}以上の要素に直接アクセスできないとな。
でも、結局Bourneでは使えない方法だから用途は限られる。
0997名無しさん@お腹いっぱい。2008/02/15(金) 23:15:51
今回は数を数えるためだけに使ってるからいいよね。
0998名無しさん@お腹いっぱい。2008/02/16(土) 01:42:35
行カウントコードの別案出してみる:

 $ (IFS='
 > '; IFS= set -- `cat foo`; echo $#)

どんな状況でも機能するのかはちょっとあれだが・・・
0999名無しさん@お腹いっぱい。2008/02/16(土) 06:58:04
h
1000小倉優子 ◆YUKOH0W58Q 2008/02/16(土) 06:58:38
1000ならジュースでも飲むか
10011001Over 1000Thread
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。
レス数が1000を超えています。これ以上書き込みはできません。