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

シェルスクリプト総合 その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 でトレースしましょう。

前スレ落ちたみたいなのでリンク省略。
0612名無しさん@お腹いっぱい。2009/04/24(金) 00:41:35
蛇の足まで描くな
0613名無しさん@お腹いっぱい。2009/04/24(金) 06:46:28
あと、sedとgrepを | でつなぐ奴とか。もうあほかと。
0614名無しさん@お腹いっぱい。2009/04/24(金) 09:27:04
でも少しずつ様子を見ながら作業してるときは、お尻に付け足すほうが
カーソル戻さなくていい分楽なのでついやっちゃうんだよな...
0615名無しさん@お腹いっぱい。2009/04/24(金) 11:10:54
>611
実行速度が大きく違う時がある
-e よりは sed | sed | sedの方が速いときもある

ケースバイケースでしょ
0616名無しさん@お腹いっぱい。2009/04/24(金) 11:47:58
>>613
インターネットで俺の悪口を言うのは止めてくれないか ><
0617名無しさん@お腹いっぱい。2009/04/24(金) 12:46:50
オレのことではないと分かってほっと一息
0618名無しさん@お腹いっぱい。2009/04/24(金) 19:58:34
sedの件ありがとうございます
ただひとつの場合-eはなくてもいいのに複数の場合は必須なんですね?
0619名無しさん@お腹いっぱい。2009/04/24(金) 20:08:32
>>618
>>608 の形式なら -e は不要。
0620名無しさん@お腹いっぱい。2009/04/24(金) 23:03:44
まあコマンドで出力しぼったりしてるときは grep | sed とか書いてもいいべ
0621名無しさん@お腹いっぱい。2009/04/25(土) 04:52:34
sedが3つも起動されてるのはどうだか。
0622名無しさん@お腹いっぱい。2009/04/25(土) 09:27:36
いまどきのマシンなら3つぐらい余裕で動く
0623名無しさん@お腹いっぱい。2009/04/25(土) 09:49:23
>>615
sed 's/afo/moe/g;s/unko/umai/g;s/ahya/uhyo/g'
よりも、
sed | sed | sed の方が速いことはあり得ない。

×ケースバイケース
>>615 の負け惜しみ
0624名無しさん@お腹いっぱい。2009/04/25(土) 10:29:36
615は -e って言ってるのに
0625名無しさん@お腹いっぱい。2009/04/25(土) 12:07:39
>>624
>>615 は一言で言い表すために -e って言っただけだろ。
-e でも>>623 でも同じこと。

まとめると、
>>611 (-e) または >>623 の方が速い。
間違っても、>>615 が言う sed | sed | sed の方が速くなるケースは無い。
0626名無しさん@お腹いっぱい。2009/04/25(土) 16:57:49
シングルなのかクアッドなのかに寄っても違うとか?
まあsed実行中もshellが居座ってるのもなんだかなあだけど。
0627名無しさん@お腹いっぱい。2009/04/25(土) 17:41:53
shellが居座るってよくないの?
そのshell分、ちょっぴりメモリを食うだけでしょ

他になんかデメリットってあるんでしょうか?
0628名無しさん@お腹いっぱい。2009/04/25(土) 18:30:21
下流のsedにshellはいないんじゃないの?
0629名無しさん@お腹いっぱい。2009/04/25(土) 18:32:17
あいや、なんか変な言い方になったな
0630名無しさん@お腹いっぱい。2009/04/25(土) 18:46:52
コマンドがひとつだけなら、
exec command
とやって、forkせずにシェルをコマンドに化けさせられる。

2つ以上のコマンドをパイプする場合は、execが使えない。
敢えて exec を付けても無意味。実験してみればわかる。
0631名無しさん@お腹いっぱい。2009/04/25(土) 22:25:15
>>626はアホなのでスルー推奨
0632名無しさん@お腹いっぱい。2009/04/26(日) 01:12:31
OSごと仮想化されてる時代に慎ましいスレですね
0633名無しさん@お腹いっぱい。2009/04/26(日) 01:20:05
いつまでもシェルスクリプトは使われるだろうね
0634名無しさん@お腹いっぱい。2009/04/26(日) 02:03:58
>>633
そりゃFortran・COBOL・Lispが未だに現役なわけだし。
0635名無しさん@お腹いっぱい。2009/04/26(日) 05:23:42
特にコボルのバッチ処理がしぶとい。
今時オンデマンドでリアルタイムで処理しろよって感じだが。
0636名無しさん@お腹いっぱい。2009/04/26(日) 06:47:10
>>635
まぁ世の中、夜間のバッチ処理に向いてる(リアルタイムに向かない)
処理もある訳で、ホストもバッチ処理もそう簡単には無くならんでしょうな。
0637名無しさん@お腹いっぱい。2009/04/26(日) 22:31:52
海外のフォーラムをみていたけど、意外とksh派って多いんだね
bash 3.5, ksh 3.5, zsh 2, csh(tcsh) 1って感じだった
他のマイナーなShellは出てこず

kshの良い点としてvi-likeの編集機能を何名かがあげていたんですけど、そんなに便利なんでしょうか?
0638名無しさん@お腹いっぱい。2009/04/26(日) 22:47:32
set -o vi となんか違う?
0639名無しさん@お腹いっぱい。2009/04/27(月) 02:51:03
こういうのできるんだね
vi `locate filename.sh`

クドイほどtips and 例文満載の文書ってないのかな
0640名無しさん@お腹いっぱい。2009/04/27(月) 04:44:20
>>637
弱い犬ほど良く吠えるから
発言が活発=利用者が多い
じゃないよ
cshやbash以外は普及してるかと言われればそうでもない
0641名無しさん@お腹いっぱい。2009/04/27(月) 06:35:18
>>640
/bin/shの実体が何かによって利用者の数は決まる気がする。
0642名無しさん@お腹いっぱい。2009/04/27(月) 09:32:46
>>639
vi +/PATTERN `egrep -l PATTERN *`
ってのは良くやるからシェルスクリプトにしてる。
0643名無しさん@お腹いっぱい。2009/04/27(月) 23:29:03
サンクコストだったっけ?>無駄金を諦める
0644名無しさん@お腹いっぱい。2009/04/28(火) 00:07:22
kshはWindowing Korn Shellに憧れたなぁ
結局公開されたkshにはその機能がなくて一度も見ることなく終わったのだが、
どんなもんだったか証言できる人はいますか?

これが使えていたらTcl/Tkとかたぶんやってなかった。
0645名無しさん@お腹いっぱい。2009/04/28(火) 01:11:38
>>644
DeskTop Korn SHellな。
http://www.brendangregg.com/DtkshDemos/xpong
0646名無しさん@お腹いっぱい。2009/04/28(火) 10:24:05
Solarisには普通に入ってなかったっけ?>dtksh
0647名無しさん@お腹いっぱい。2009/04/28(火) 15:36:56
>>645,646
トン。dtkshだったのか。いままで検索しても画面を拝めなかったので
もう見ることはないかと思ってたよ。おかげで

 http://docs.sun.com/app/docs/doc/805-3917/6j3niaoaf?l=Ja&a=view

のプログラミングマニュアルでコードとか動作を初めて拝めた。
Solarisは使ってるけど/usr/dtとかまず使わないからまったく知らなかった。
もしかしてOpenSolarisにも入っているのだろうか・・・

Xツールキットの関数とオプションのまんまラッパーだったんだな。
今見るとベタで微笑ましい位。さすがにスクリプトででもXtは使いたいとは
もう思えないが、当時使えていたらハマッただろうなぁ。
0648名無しさん@お腹いっぱい。2009/04/28(火) 18:39:57
すごいくだらない質問ですまない。
/tmp/old まであるディレクトリ構造で
単純に/tmpディレクトリにあるファイルリストをテキストで出したいのだけど
ディレクトリや隠しファイルの表示は入れたくない
どんなコマンドつかえばできる?
lsやfindでいろんなオプションつけてやってみたけど無理だった
たぶんすごく単純なところで引っ掛かってる気がするので、わかる方いたら教えてください
0649名無しさん@お腹いっぱい。2009/04/28(火) 19:27:00
find /tmp -maxdepth 1 -type f
0650名無しさん@お腹いっぱい。2009/04/28(火) 19:29:16
>>649
隠しファイルの表示は入れたくない
0651名無しさん@お腹いっぱい。2009/04/28(火) 19:30:52
>>648
cd /tmp; for file in *; do [ -f "$file" ] && echo "$file"; done
0652名無しさん@お腹いっぱい。2009/04/28(火) 19:38:57
find内で.*を排除するほうがいいだろう。
くだ質スレでほぼ解決してるからここ見に来るとは思わんけど。
0653名無しさん@お腹いっぱい。2009/04/28(火) 19:42:22
>>652
find内で.*を排除するのは無駄だろ。
せっかく内部コマンドだけでできるのに。
0654名無しさん@お腹いっぱい。2009/04/28(火) 19:44:13
>>652
あっちでやってるのは、find「内」じゃないだろ。
findの「外」のパイプに出してからあとからカットしてる。ノンエレガント。
0655名無しさん@お腹いっぱい。2009/04/28(火) 19:47:52
外部コマンド | 外部コマンド

よりも、

シェル内部コマンドのみ

の方が速いわな。
0656名無しさん@お腹いっぱい。2009/04/28(火) 19:49:47
>>652
find方式だと、「hoge<改行>.hoge」みたいなファイル名があった場合、誤動作する。

>>651 方式なら無問題。
0657名無しさん@お腹いっぱい。2009/04/28(火) 20:17:44
[ が内部コマンドなシェルならいいけど、
外部コマンドなシェルだとパフォーマンス最悪
0658名無しさん@お腹いっぱい。2009/04/28(火) 20:39:13
コストだとかケチくせぇことはいいんだよ。
0659名無しさん@お腹いっぱい。2009/04/28(火) 21:12:44
>>651はファイル名にシーケンス文字列とか含んでると一部のシェルでは誤爆すんよ

$ touch foo\\bar
$ for file in *; do [ -f "$file" ] && echo "$file"; done
foar
0660名無しさん@お腹いっぱい。2009/04/28(火) 21:12:51
[ が外出しのシェルなんて現存しないから。あ、NGワードMINIXな。
0661名無しさん@お腹いっぱい。2009/04/28(火) 21:14:33
>>659
for f in *; do [ -f "$f" ] && printf '%s¥n' "$f"; done
0662名無しさん@お腹いっぱい。2009/04/28(火) 21:30:00
>>660
v7sh
echoも外出し。
0663名無しさん@お腹いっぱい。2009/04/28(火) 21:33:48
>>660
FreeBSD tcsh
% which [
/bin/[
0664名無しさん@お腹いっぱい。2009/04/28(火) 21:48:08
>>663
>>661 で for文使ってるのが見えねぇのかよw

>>662
v7は「現存」しない。
0665名無しさん@お腹いっぱい。2009/04/28(火) 21:51:34
cd /usr/ports/shells/v7sh; make install
0666名無しさん@お腹いっぱい。2009/04/28(火) 21:55:13
>>665
やっぱり「現存」しないじゃん。

わざわざ作らなきゃいけないんだから。
0667名無しさん@お腹いっぱい。2009/04/28(火) 21:57:57
この流れ、前も見た気がするけど、
「testやechoが外部コマンドの場合もある」って主張してる人、
実際そんな古いシェルを「ログインシェル」または「スクリプトシェル」として
現役で使ってるの?

使ってないのに机上の空論してもしょうがないよ。
0668名無しさん@お腹いっぱい。2009/04/28(火) 22:02:39
そんなことはどうでもいい
0669名無しさん@お腹いっぱい。2009/04/28(火) 22:08:53
testを使わない方法を考えてみた。

for f in *; do (cd "$f") 2> /dev/null || echo "$f"; done

Permission deniedなディレクトリがあったら誤判定されるのは仕方ない。
0670名無しさん@お腹いっぱい。2009/04/28(火) 22:14:47
> 誤判定されるのは仕方ない。
> 誤判定されるのは仕方ない。
> 誤判定されるのは仕方ない。
> 誤判定されるのは仕方ない。
0671名無しさん@お腹いっぱい。2009/04/28(火) 22:16:41
>>669
v7sh
cdも外出し。
0672名無しさん@お腹いっぱい。2009/04/28(火) 22:29:15
>>669
誤判定されない方法を考えてみた。

for f in *;do case `(cd "$f") 2>&1` in *'Not a directory')echo "$f";;esac; done
0673名無しさん@お腹いっぱい。2009/04/28(火) 22:56:37
>>647
> もしかしてOpenSolarisにも入っているのだろうか・・・

入ってない。TODOリストに入っているが、
ライセンス関係で新たに作らないといけない。
CDE/Motifべったりだから誰もやらないだろう。

>>666
わざわざエミュレータで動かしてます。
「現存」してないです。とあなたは言うでしょうけど。
0674名無しさん@お腹いっぱい。2009/04/29(水) 01:06:42
648は満足したのかな。
0675名無しさん@お腹いっぱい。2009/04/29(水) 02:37:45
testの内部コマンド化は実用の観点ではぜひ必要だが
美しくないな。
なんてこと言う奴はrcを使えってことか
0676名無しさん@お腹いっぱい。2009/04/29(水) 05:58:40
>>664
> v7は「現存」しない。
うちでは fpga で作った pdp-11 互換 CPU 上で元気に動いてますけど
0677名無しさん@お腹いっぱい。2009/04/29(水) 05:59:43
> cdも外出し。
寝言は寝てから言ってね
0678名無しさん@お腹いっぱい。2009/04/29(水) 06:49:51
>>676
それを「現存しない」と言う。よく覚えとけ。
0679名無しさん@お腹いっぱい。2009/04/29(水) 06:55:31
Solarisでは cdは外出しだよ。
/usr/bin/cd コマンドが存在するし。

多分、親プロセスを chdir()するようなシステムコール? を呼んでる??
0680名無しさん@お腹いっぱい。2009/04/29(水) 08:08:58
>>679
それたしか、自分がcdするだけ、ってnopコマンドじゃなかった?
0681名無しさん@お腹いっぱい。2009/04/29(水) 08:30:53
いや、ちゃんとcdでディレクトリ変わるし、which cd で /usr/bin/cdって出るんだ。
0682名無しさん@お腹いっぱい。2009/04/29(水) 08:59:20
>>681
/usr/bin/cd fooとやると変わらないだろ。
/usr/bin/cd foo && cd fooでフェイルセイフなcdだ。
0683名無しさん@お腹いっぱい。2009/04/29(水) 09:09:49
>>682
> /usr/bin/cd foo && cd fooでフェイルセイフなcdだ。

それ、フェイルな場合 /usr/bin/cd の段階でフェイルして、
エラーメッセージも出てしまうから、ちっともフェイルセーフじゃない。
単に cd foo とやったのと何ら変わりない。
0684名無しさん@お腹いっぱい。2009/04/29(水) 09:28:49
>>679
> 多分、親プロセスを chdir()するようなシステムコール? を呼んでる??
そんなシステムコールあるわけねーだろw
0685名無しさん@お腹いっぱい。2009/04/29(水) 09:39:00
おれ、今OS自作してるけど、fork()の引数でSHARE_CWDをセットすると
子プロセスとカレントディレクトリを共有する仕様にしようと思ってる。
cdを外付けコマンドにしたシェルを実装するんだ。
0686名無しさん@お腹いっぱい。2009/04/29(水) 09:40:04
フラグ乙
0687名無しさん@お腹いっぱい。2009/04/29(水) 09:43:41
あと、SHARE_ENVとSHARE_FDもつければいい
0688名無しさん@お腹いっぱい。2009/04/29(水) 09:47:47
>>685
それ、cdのときだけSHARE_CWDをセットするんなら、cdだけ特別扱い変わらず?
0689名無しさん@お腹いっぱい。2009/04/29(水) 09:54:11
fork()じゃなくてclone()だろ
0690名無しさん@お腹いっぱい。2009/04/29(水) 11:02:21
我が家のアイデア料理の話は要らないから
既存のシェルスクリプトの話をしろよ
0691名無しさん@お腹いっぱい。2009/04/29(水) 15:12:02
シェルってコンピューター用語だよ。
貝料理のことじゃないよ。誰も料理の話はしていないよ。
0692名無しさん@お腹いっぱい。2009/04/29(水) 16:36:32
つまんね
0693名無しさん@お腹いっぱい。2009/04/29(水) 22:08:15
>>678
日本語が不自由な人か?
ちゃんと、未だにPDP-11互換CPU上でV7が動いているんだから
「現存しない」とは言わないと思うぞ
実際にV7が動いてるわけだから
0694名無しさん@お腹いっぱい。2009/04/29(水) 22:14:28
そんなこと言ったら、博物館で復刻動作してる物でも「現存する」ことになってしまう。

testやechoが外部になってるシェルの議論なんてしても無駄。
0695名無しさん@お腹いっぱい。2009/04/29(水) 22:20:02
V7はソース見るとあまりにスッキリしすぎ。
(shは伝説的変態だが)
実際使うとすぐ落ちるんじゃないか?
0696名無しさん@お腹いっぱい。2009/04/29(水) 22:24:31
>>694
現実に動作してるじゃん
それを使う機械の有無は別として
シーラカンスは現存してないものって言ってるのに等しい
0697名無しさん@お腹いっぱい。2009/04/29(水) 22:26:47
>>695
はあ?
普通に使ってますけど?
0698名無しさん@お腹いっぱい。2009/04/29(水) 22:29:24
このスレは、実際にシェルスクリプトを使って仕事をしている人同士の
情報交換なので、個人的な趣味で過去の機械を動かして満足してる人は
無理に話題に入ってこないでいただけるかな?
0699名無しさん@お腹いっぱい。2009/04/29(水) 22:46:36
なんで仕事している人に限定すんだよ
0700名無しさん@お腹いっぱい。2009/04/29(水) 23:49:38
いいレスなら空想家も歓迎。
0701名無しさん@お腹いっぱい。2009/04/30(木) 01:08:37
爺さんが使っているポンコツの話なんぞ、誰も聞きたくないんですよ。
いい加減にしてね(はーと)。
0702名無しさん@お腹いっぱい。2009/04/30(木) 01:10:34
>>701
じゃあ、ネタ振ってよ はーと
0703名無しさん@お腹いっぱい。2009/04/30(木) 11:45:55
>>698
> このスレは、実際にシェルスクリプトを使って仕事をしている人同士の情報交換
ダウト。
>>1には、お勉強・自慢・腕試しと明記されている。従って、趣味でシェルスクリプ
トを勉強している人もOKだろ。


0704名無しさん@お腹いっぱい。2009/04/30(木) 18:33:49
getoptとgetoptsってどっち使ってる?
0705名無しさん@お腹いっぱい。2009/04/30(木) 18:40:44
当然getopts

getoptは外出しの別物
0706名無しさん@お腹いっぱい。2009/04/30(木) 18:42:07
速度的にはビルトインのgetoptsのほうが速いのはわかるけど
オプションの処理なんてたかが知れてるし

その他の面でもgetoptsのほうがいいの?
0707名無しさん@お腹いっぱい。2009/04/30(木) 18:46:55
getoptって、スペース入りファイル名とか、ちゃんと処理できたっけ?
getoptsならもちろん無問題だけど。
0708名無しさん@お腹いっぱい。2009/05/02(土) 01:11:20
質問です。

以下のような形式のログ(MySQLのバイナリログみたいなもの)があるとします。
---------------------
09/04/01 12:00 aaa
09/04/01 13:10 aaa
          bbb
09/04/01 13:20 ccc
09/04/01 14:40 aaa
          ddd
          eee
          ccc
---------------------
このような形式のログから、例えば、13時台のログを抜き出すにはどうしたらいいでしょうか?
上記のログでいうと、以下のような結果がほしいです。
---------------------
09/04/01 13:10 aaa
          bbb
09/04/01 13:20 ccc
---------------------
awkとgrepを駆使すればできそうなのですが、いまいちわかりません。
よろしくご教示お願いします。
0709名無しさん@お腹いっぱい。2009/05/02(土) 02:24:32
>>708
aaa や bbb がスペースやTABで分割された複数の単語(bbb = xxx xxx ...)になることが無いなら

awk 'NF>2{if($2~/^13:[0-5][0-9]$/)f=1;else f=0}f==1' "ログファイル"

複数の単語になるが bbb = xxx 00:00 xxx ... みたいに2番目の要素が時刻形式になることが絶対無いなら

awk '$2~/^[0-9][0-9]:[0-9][0-9]$/{if($2~/^13:[0-5][0-9]$/)f=1;else f=0}f==1' "ログファイル"


でいけそうな気がする。手元に環境ないんで試せてないけど
0710名無しさん@お腹いっぱい。2009/05/02(土) 02:35:06
grepがいいんじゃない?
cat 2ch-708-20090501.data | grep "[0-9]\{2\}/[0-9]\{2\}/[0-9]\{2\} 13:"
冗長的に書くとこんな感じ
cat 2ch-708-20090501.data | grep "[0-9][0-9]/[0-9][0-9]/[0-9][0-9] 13:"

man grepを読んで、cat data | grep うんたらで正規表現を試すといいと思うよ
0711名無しさん@お腹いっぱい。2009/05/02(土) 04:37:38
それじゃ駄目
■ このスレッドは過去ログ倉庫に格納されています