シェルスクリプト総合 その14
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
2009/01/29(木) 06:54:48スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>1-6くらい)をご覧ください。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
Linuxユーザは/bin/shの正体がbashなので特に注意。
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でそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
前スレ落ちたみたいなのでリンク省略。
0525名無しさん@お腹いっぱい。
2009/04/20(月) 07:25:46不用意な展開を防ぐため。
基本はすべてシングルクォート。
$HOGE とか `com` とか、展開が必要な時のみダブルクォート、というのがルール。
0526名無しさん@お腹いっぱい。
2009/04/20(月) 07:44:04さんくす
もっといっぱい本を読んで、写経します
0527名無しさん@お腹いっぱい。
2009/04/20(月) 09:31:41kshの速さを実感して貰えて何より。
いまいちマイナーなのが不思議だったりする。
0528名無しさん@お腹いっぱい。
2009/04/20(月) 12:48:180529名無しさん@お腹いっぱい。
2009/04/20(月) 12:58:57昔はこぞってみんな使ってたんだぜ。
bashがなかった時代だけど。
0530名無しさん@お腹いっぱい。
2009/04/20(月) 13:16:27自分ルールを標準のごとく言ったりエレガントとか言うのはどうかと思う
520〜523までなら後から見たときや他人が書いたものを見たとき520が一番見やすい
echo の内容を | を通して渡す為に >>523 にしたというならともかく(この場合でも他に方法はいくらでもあるけど)
0531名無しさん@お腹いっぱい。
2009/04/20(月) 14:16:51マイナーという
0532名無しさん@お腹いっぱい。
2009/04/20(月) 14:17:410533名無しさん@お腹いっぱい。
2009/04/20(月) 14:35:10なぜかOpenBSDで使われているShellって感じですね
2000年まで、Korn shell は AT&T の権利保有するソフトウェアであった。その後AT&T独自
のライセンスの下でオープンソースとなり、2005年から Common Public License での配布
となった。Korn shell は AT&T Software Technology (AST) Open Source Software
Collection の一部として入手可能である。
と書いてあるけど、2000年以前は無料で使えなかったんでしょうか?
10年前ぐらい訳本には商用うんぬんと書いていないから15年前ぐらいからは入手的には困らなかったんだろうか
OpenBSD誕生が1996年みたいだけど、標準Shellは、なんだったのだろうか
最初からksh?
あとなんちゃってUNIXユーザーとしては、知名度だと
bash >>> sh >= zsh >= tcsh >> csh > ksh ぐらい違う
それ以外のマイナーなShellは、自分の中に存在しません
>>529
bash誕生が1987年、Linux誕生が1991年なんですけど、簡単にbashは入手しづらかったんでしょうか?
>>531
Linuxだと標準では入っていないけど、kshは入れるものなんでしょうか?
ビジネスでの普及度はどんな感じなんですか?
対話シェルはbashとか、他のなにかでshスクリプトの実行はkshって感じなんでしょうか?
それともshに対応しないkshスクリプトを書くの?
>>532
今でもひそかなファンが多いし、重宝されていると言えばいいのかな
0534名無しさん@お腹いっぱい。
2009/04/20(月) 14:40:33>それともshに対応しないkshスクリプトを書くの?
普通書かない。
shに対応しないkshスクリプトの代表例と言えば [[ ]] の記述。
sh的には if [ "$hoge" = fuga ]; then と書くところを、
kshでは if [[ "$hoge" == fuga ]]; then と書く。
でも、こんなの滅多に見ないだろ。それほど kshはマイナー。
0535名無しさん@お腹いっぱい。
2009/04/20(月) 15:02:26Linuxには入れちゃうよーん
0536名無しさん@お腹いっぱい。
2009/04/20(月) 15:27:090537名無しさん@お腹いっぱい。
2009/04/20(月) 16:31:480538名無しさん@お腹いっぱい。
2009/04/20(月) 16:35:48特に自社システムじゃなく受託開発なら
トラブル時に責任問題にもなる
0539名無しさん@お腹いっぱい。
2009/04/20(月) 16:39:400540名無しさん@お腹いっぱい。
2009/04/20(月) 16:41:470541名無しさん@お腹いっぱい。
2009/04/20(月) 16:43:27具体的には?
0542名無しさん@お腹いっぱい。
2009/04/20(月) 16:57:46それぞれのベンダが提供しているやつ
0543名無しさん@お腹いっぱい。
2009/04/20(月) 17:08:150544名無しさん@お腹いっぱい。
2009/04/20(月) 17:21:190545名無しさん@お腹いっぱい。
2009/04/20(月) 21:06:27プログラム 'ksh' は以下のパッケージで見つかりました:
* ksh
* mksh
* zsh
* pdksh
次の操作を試してください: sudo apt-get install <選択したパッケージ>
やはりここはpdksh?
0546名無しさん@お腹いっぱい。
2009/04/20(月) 21:46:52起動からの経過時間でなく、起動日時です。
出来ればシリアル値(1970からの経過秒)で取得できれば嬉しいです。
uptimeの結果から計算するのは起動からの経過時間によってフォーマットが
(daysやminが付いたり、付かなかったり)違うため出来れば避けたいです。
GNU、bash依存でもかまいません。
0547名無しさん@お腹いっぱい。
2009/04/20(月) 21:52:230548名無しさん@お腹いっぱい。
2009/04/20(月) 21:56:220549名無しさん@お腹いっぱい。
2009/04/20(月) 21:58:370550名無しさん@お腹いっぱい。
2009/04/20(月) 22:14:36GNU 依存でいいなら、
date -r /
(ルートディレクトリのタイムスタンプは起動時に touchされて
その後書き込みは普通は発生しないことを利用)
0551名無しさん@お腹いっぱい。
2009/04/20(月) 22:18:322009年 2月 6日 金曜日 21:12:47 JST
ずれまくりワロタ
0552名無しさん@お腹いっぱい。
2009/04/20(月) 22:24:36好きにすればいいじゃない
0553名無しさん@お腹いっぱい。
2009/04/20(月) 22:31:52OpenBSD on VMware on WindowsXPでやったら、Thu Jan 1 09:00:00 JST 1970になった
まあ、OpenBSD on VMwareだからしゃないやな
0554553
2009/04/20(月) 22:46:48Scientific on VMware,Fedora11 on VMwareだとちゃんと出るんだな
まあ、どうでもいい話でした
0555501
2009/04/21(火) 00:03:03ただしおいらの環境だと、>>511さんのプログラムのままでは
2009/04/19 01:23:45,user,ip=[192.168.1.2]
のような結果になってしまうので、whileのダミー引数を増やしました。
最終的にこんな感じにしますた。
(※全角スペースでインデントしています)
----
#!/usr/local/bin/ksh
YEAR=`date +'%Y'`
while IFS=' =,[]' read mon day time d1 d2 d3 d4 d5 d6 d7 d8 user d9 d10 ip d11
do
case $mon in
Jan)mon=01;; Feb)mon=02;; Mar)mon=03;; Apr)mon=04;;
May)mon=05;; Jun)mon=06;; Jul)mon=07;; Aug)mon=08;;
Sep)mon=09;; Oct)mon=10;; Nov)mon=11;; Dec)mon=12;;
esac
echo $YEAR/$mon/$day $time,$user,$ip
done
----
0556501
2009/04/21(火) 00:07:41スクリプトの実行速度なんですが、約10万行のログを処理したところ、
kshではなんと4秒で終わっちゃいました。
ちなみに/bin/shで動かしたら、27秒もかかっちゃいまして、
処理性能の違いに驚いた次第であります。
おまいら、ありがとうございますた。
0557名無しさん@お腹いっぱい。
2009/04/21(火) 01:03:04ちなみにOSは?
0558名無しさん@お腹いっぱい。
2009/04/21(火) 01:13:39報告おつ
比較をわかりやすく、30万行じゃないのねw
6.75倍はすごいね
0559501
2009/04/21(火) 01:26:31処理時間を計ったのはVMware上で動いているFreeBSD7.1ですが、
Solaris9(SPARC)でも動くのは確認しますた。
>>558
手元にあったのが10万行のログだったので、
とりあえずこれで試しますた。
深い意味はありませんw
0560名無しさん@お腹いっぱい。
2009/04/21(火) 01:31:08こんなのどうかな。
GNU依存だし、動かないパターン多そうだけど。
$ last | grep '^reboot' | head -1 | awk '{print $5" "$6" "$7" "$8}' | date -f - '+%s'
0561名無しさん@お腹いっぱい。
2009/04/21(火) 01:40:080562名無しさん@お腹いっぱい。
2009/04/21(火) 01:50:16wtmp って1月分しか残らないんだっけ?
そう言えば、/proc/uptime はサイズどれだけ有るんだっけ(溢れることはない?)?
0563名無しさん@お腹いっぱい。
2009/04/21(火) 03:07:540564名無しさん@お腹いっぱい。
2009/04/21(火) 03:55:340565名無しさん@お腹いっぱい。
2009/04/21(火) 07:16:33たとえば、
echo $((x > 0 ? x: -x))
とか。
0566名無しさん@お腹いっぱい。
2009/04/21(火) 07:38:41A && (B; true) || C
かと。
0567名無しさん@お腹いっぱい。
2009/04/21(火) 08:20:54アフォか。
それは普通の「2項」の演算子の組み合わせ。
しかも、bash限定でもない。
>>565 が正解。
0568名無しさん@お腹いっぱい。
2009/04/21(火) 09:59:52>>567は>566に輪をかけたアフォ。
「bashで」というお題は「bash以外では動作しない == bash限定」事を要求していない。
0569名無しさん@お腹いっぱい。
2009/04/21(火) 10:53:47はりきるだけだから
0570名無しさん@お腹いっぱい。
2009/04/21(火) 11:12:24ここでのベンチ(kshとbash)は、ライブラリが動的か静的かよりもはるかに大きい
差を生じているので、そんな点を指摘しても無意味。
さらにアフォな点は、バイナリは「スタティックリンク」の方が速い(有利)ということ。
>>564 は全く逆に覚えてるようだね。
0571名無しさん@お腹いっぱい。
2009/04/21(火) 12:34:230572名無しさん@お腹いっぱい。
2009/04/21(火) 12:40:45素で質問してるならぐぐれ。
釣りなら面白くない。
0573名無しさん@お腹いっぱい。
2009/04/21(火) 13:33:19以下のスクリプトでエラーが出ます。
num=1
for file in *.m4a; do
mv $file $num.m4r
num=`expr $num + 1`
done
エラーは
mv: target `1.m4r' is not a directory
というものです。
シェルというよりmvコマンドの使い方の問題なのかもしれませんが
自分には原因がわかりません
教えてください
0574名無しさん@お腹いっぱい。
2009/04/21(火) 13:42:53共有ライブラリは間接呼出しになる。
0575名無しさん@お腹いっぱい。
2009/04/21(火) 13:44:59スペース入りファイル名が分割されて、
mv hoge hage.m4a 123.m4r
みたいに実行されたのが原因。
シェル変数の展開時には原則すべてダブルクォートを付けること。
mv "$file" "$num.m4r"
0576名無しさん@お腹いっぱい。
2009/04/21(火) 13:45:06ファイル名に空白(やタブ等)が含まれているのだろう。
mv "$file" $num.m4r
0577名無しさん@お腹いっぱい。
2009/04/21(火) 14:04:48>>576
なるほど、そういうことだったんですか!
まさにその通りで、ファイル名にスペースが入っていました。
ありがとうございます!
0578名無しさん@お腹いっぱい。
2009/04/21(火) 21:57:17すごく適当ですが・・・・こんな感じで OS ごとに書くしかないかと。
case `uname -s` in
'Linux')
grep btime /proc/stat | cut -d ' ' -f 2
;;
'FreeBSD')
cut -d ' ' -f 8 /proc/1/status | cut -d ',' -f 1
;;
*)
;;
esac
0579名無しさん@お腹いっぱい。
2009/04/22(水) 05:32:25ダイナミックが遅いなら、みんなダイナミック使ってないwww
perlとかも普通はダイナミック。
0580名無しさん@お腹いっぱい。
2009/04/22(水) 06:10:01オマエ真性の勘違い野郎か。
スタティックリンクでも全部は読み込まない。
仮想記憶って知ってるか?
バイナリプログラムのうち、実際にCPUのプログラムカウンタが走った命令のアドレス
を含むメモリページのみが読み込まれる。実行されなかった部分は読み込まれない。
ダイナミックリンクのライブラリは、リロケーションの関係で、
PIC(ポジションインディペンデント)にコンパイルする必要があり、
PIC自体が通常のバイナリよりも数%遅い。
ライブラリのキャッシュについては確かにいうとおりだが、
これは他の要素に比べて影響は小さいので、
やはりダイナミックリンクの方が遅い。
ダイナミックリンクは遅いが、HDDの節約や、ライブラリのupdateの際に
リンクしてる個々のバイナリを再コンパイルしなくて良い便宜のために
使用されている。どうしても速度優先の場合は、
スタティックリンクを使うことがあるよ。
0581名無しさん@お腹いっぱい。
2009/04/22(水) 06:36:28ライブラリは複数の関数の集まりでできているが、
スタティックリンクの場合、それらの関数のうち、使用している関数だけが
コンパイル(ld)時にリンクされる。使っていない関数はそもそもリンクされない。
(使っていても条件によって呼び出されなかった関数は
仮想記憶によってメモリにはロードされないままになる可能性があるのは
>>580 がいう通り)
ダイナミックリンクの場合は、使っていない関数まで
実行時に塊で付いてきてしまう。
0582名無しさん@お腹いっぱい。
2009/04/22(水) 06:57:20それよりもバイトコンパイルやらコマンド組み込みやらの方が効果でかいはず。
0583名無しさん@お腹いっぱい。
2009/04/22(水) 07:57:48間違った知識ばらまいてないで、実験してみればいいのに。
$ cat hoge.c
#include <stdio.h>
int main(){printf("Hello¥n");return 0;}
$ gcc -o dynamic hoge.c
$ gcc -o static hoge.c -static
$ time ./dynamic
Hello
real 0m0.004s
user 0m0.000s
sys 0m0.001s
$ time ./static
Hello
real 0m0.002s
user 0m0.000s
sys 0m0.000s
スタティックリンクの方が速いね。
0584名無しさん@お腹いっぱい。
2009/04/22(水) 09:15:01ミリ秒オーダでしか違わないんじゃほとんどの場合は
そんなこと気にするよりまともなプログラム書いたほうが
いいなw
0585名無しさん@お腹いっぱい。
2009/04/22(水) 09:37:11dynamicもstaticも「ほとんど違わない」ので、それ以外の要素による違いの方が大きい
ということは元々 >>570 が指摘してる。(こっちが要点)
それ以外に、>>564 は「ダイナミックの方が速い」と間違ってることを言ってるるので、
それをついでに指摘しただけ。
で、>>579 で未だに「ダイナミックの方が速い」の主張を続けるから、
>>580 がそれを否定しているだけ。
別に>>580 が、シェルスクリプトのシェルをスタティックにしろと主張している
わけではない。
元の質問に戻って、>>508 の場合、外部コマンドの cutの呼び出しが多数ループ
されるので、それが遅かったのが原因と思われる。
>>511 はシェルの内部コマンドだけを使っているので、それで激劇に速くなったと。
いすれにしても、その話の流れを読まずに
>>564 で見当違いかつ間違った指摘をしている >>564 はアフォ。
0586名無しさん@お腹いっぱい。
2009/04/22(水) 10:22:55> ライブラリのキャッシュについては確かにいうとおりだが、
> これは他の要素に比べて影響は小さいので、
> やはりダイナミックリンクの方が遅い。
嘘八百のおバカさん
0587名無しさん@お腹いっぱい。
2009/04/22(水) 10:31:05主張する内容自体に問題くても、必死すぎるとキモいものだな...
まあ落ち着け。
0588名無しさん@お腹いっぱい。
2009/04/22(水) 10:35:53>>579 は perlの「ダイナミックロード」のライブラリ(モジュール)の話と
混同してるフシがあるな。(わざわざ的外れなperlを例に持ち出してきてるあたり)
>>579 にとって、「ダイナミック」とは、perlでしかイメージできてなくて、
普通にCをコンパイルする時のstatic linkとdynamic linkを違いを
全く理解できてない(存在自体知らない?)んだろう(笑)
0589名無しさん@お腹いっぱい。
2009/04/22(水) 10:49:32問題です。
Ubuntuでは、dashをビルドする際に、libcを使わずdietlibcに変更した上で、
スタティックリンクしています。これはなぜでしょうか。
ヒント:Ubuntuでは/bin/shとしてdashを使っています。
0590名無しさん@お腹いっぱい。
2009/04/22(水) 11:07:22スタティックリンクの方が速いからではない。
そもそも速くないし。
0591名無しさん@お腹いっぱい。
2009/04/22(水) 11:11:36>そもそも速くないし。
↑
は間違い。実際速い。
それ以外にstatic linkにする利点と、さらにdietlibcに変更する理由を質問してる。
>>590 では答えになっていない。
ハイ、答え直し >>590 >>584
↓
0592名無しさん@お腹いっぱい。
2009/04/22(水) 11:12:45ちゃんと自分の頭を使って自分の体を動かして自分の目で確認しろよ。
0593名無しさん@お腹いっぱい。
2009/04/22(水) 11:31:22NSS まわりとかで必要があれば勝手にダイナミックでリンクしちゃうから
わりとどーでもいい。
0594名無しさん@お腹いっぱい。
2009/04/22(水) 11:47:34争点をぼかすことになるから、ここでは dlopen()系の話は持ち込まない方が
話が簡単になるかと。どうせあほは >>579 1人だろうし。
0595名無しさん@お腹いっぱい。
2009/04/22(水) 12:33:36しかもdietlibcはLGPLでなくGPLなのでダイナミックリンクでも汚染する。
0596名無しさん@お腹いっぱい。
2009/04/22(水) 12:35:04すさまじい勘違いだなw
0597名無しさん@お腹いっぱい。
2009/04/22(水) 12:38:47このオーダーも特に速度が必要な場合は馬鹿に出来ないよ。
まぁ、dynamicかstaticかの違いより、根本的な設計の方がよっぽど大きいけど。
0598名無しさん@お腹いっぱい。
2009/04/22(水) 12:49:51ミリ秒オーダーの起動オーバヘッドが問題になるほど実行時間の
短いプログラムを何度も起動するのはそもそも設計が悪いよね
0599名無しさん@お腹いっぱい。
2009/04/22(水) 12:59:45オーバヘッドは「プログラム起動時」だけじゃないよ。
dynamicなライブラリ上の関数を呼び出すたびにオーバーヘッドがかかる。
さらに、関数自体がPICによって速度上不利なコードで書かれているから遅くなる。
staticライブラリなら、プログラム中に絶対アドレスを決めうちで持つから、
その分のオーバーヘッドがなく高速動作する。
0600名無しさん@お腹いっぱい。
2009/04/22(水) 13:10:18結論ありきというか
そうでないと世界が崩壊しちゃうんだろうね
0601名無しさん@お腹いっぱい。
2009/04/22(水) 13:18:31今まで「ダイナミックリンクの方が速い」と間違って覚えていて
散々恥を晒した気分はどうだい? >>600 = >>579
0602名無しさん@お腹いっぱい。
2009/04/22(水) 13:22:13自己紹介乙。
そうか、今までdynamicの方が速いと信じこんでいて、それが間違いだと知って
キミの世界が崩壊しちゃったのか、、よしよし
0603名無しさん@お腹いっぱい。
2009/04/22(水) 13:50:410604名無しさん@お腹いっぱい。
2009/04/22(水) 17:24:320605名無しさん@お腹いっぱい。
2009/04/22(水) 23:37:030606名無しさん@お腹いっぱい。
2009/04/22(水) 23:52:09ま、次から間違えないようにすれば良いじゃないか。
0607名無しさん@お腹いっぱい。
2009/04/23(木) 22:37:10という場合のsedをひとつにできますか?
0608名無しさん@お腹いっぱい。
2009/04/23(木) 22:43:22echo aaabbbccceee | sed 's/aaa//;s/ccc//'
0609名無しさん@お腹いっぱい。
2009/04/23(木) 22:55:44$ alias ひとつ=sed
$ echo aaabbbccceee | ひとつ 's/aaa//' | ひとつ 's/ccc//'
0610名無しさん@お腹いっぱい。
2009/04/23(木) 23:29:400611名無しさん@お腹いっぱい。
2009/04/24(金) 00:10:17個人的には、見やすさも考えてこんな風に書くこと多いかな。
sed -e 's/afo/moe/g' \
-e 's/unko/umai/g' \
-e 's/ahya/uhyo/g'
あと、文字列に / がいっぱい入るときは \/ じゃなくって、そもそも / を使わない。
s|/afo/desu/yo|/unko/tabe/tai/ne|
0612名無しさん@お腹いっぱい。
2009/04/24(金) 00:41:350613名無しさん@お腹いっぱい。
2009/04/24(金) 06:46:280614名無しさん@お腹いっぱい。
2009/04/24(金) 09:27:04カーソル戻さなくていい分楽なのでついやっちゃうんだよな...
0615名無しさん@お腹いっぱい。
2009/04/24(金) 11:10:54実行速度が大きく違う時がある
-e よりは sed | sed | sedの方が速いときもある
ケースバイケースでしょ
0616名無しさん@お腹いっぱい。
2009/04/24(金) 11:47:58インターネットで俺の悪口を言うのは止めてくれないか ><
0617名無しさん@お腹いっぱい。
2009/04/24(金) 12:46:500618名無しさん@お腹いっぱい。
2009/04/24(金) 19:58:34ただひとつの場合-eはなくてもいいのに複数の場合は必須なんですね?
0619名無しさん@お腹いっぱい。
2009/04/24(金) 20:08:32>>608 の形式なら -e は不要。
0620名無しさん@お腹いっぱい。
2009/04/24(金) 23:03:440621名無しさん@お腹いっぱい。
2009/04/25(土) 04:52:340622名無しさん@お腹いっぱい。
2009/04/25(土) 09:27:360623名無しさん@お腹いっぱい。
2009/04/25(土) 09:49:23sed 's/afo/moe/g;s/unko/umai/g;s/ahya/uhyo/g'
よりも、
sed | sed | sed の方が速いことはあり得ない。
×ケースバイケース
○ >>615 の負け惜しみ
0624名無しさん@お腹いっぱい。
2009/04/25(土) 10:29:36■ このスレッドは過去ログ倉庫に格納されています