シェルスクリプト総合 その16
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
2010/02/20(土) 14:10:05スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>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 でトレースしましょう。
前スレ
シェルスクリプト総合 その15
http://pc12.2ch.net/test/read.cgi/unix/1246408968/l50
0667名無しさん@お腹いっぱい。
2010/09/07(火) 01:43:34シェルスクリプトと比べてみるといいよ。
0668名無しさん@お腹いっぱい。
2010/09/07(火) 06:33:27> シェルを書かないと。
↑シェルを書いちゃう回答者現るw
0669名無しさん@お腹いっぱい。
2010/09/07(火) 08:15:010670名無しさん@お腹いっぱい。
2010/09/07(火) 08:15:290671名無しさん@お腹いっぱい。
2010/09/07(火) 09:37:54一般的な呼び方だと、ボーンシェル、Bシェル(ビーシェル)と
呼ぶんで、シェルとは呼ばない。
0672名無しさん@お腹いっぱい。
2010/09/07(火) 09:47:45そのうちshと想定して回答しただけだろ
字面で反応した恥ずかしいミスを指摘されてキョドるなよ
0673名無しさん@お腹いっぱい。
2010/09/07(火) 09:59:19スクリプトの前にアンカー覚えろよ
0674名無しさん@お腹いっぱい。
2010/09/07(火) 12:29:12これって「数値計算」をシェルスクリプトでやってるのかなあ?
0675666
2010/09/07(火) 12:30:37科学計算についてどの程度知った上でのレスでしょうか?
300個ある実行シェルスクリプトは全て、中でFortranのプログラムを呼び出しているだけです。
シェルスクリプトは初期値や環境変数の設定に使うだけであって、それで数値計算しているわけではないです。
『Perlで書いてみて』というのは、具体的にどの部分を言っているのですか?
0676666
2010/09/07(火) 12:32:320677名無しさん@お腹いっぱい。
2010/09/07(火) 12:55:12情報後出し祭りに突入してきましたよ
0678名無しさん@お腹いっぱい。
2010/09/07(火) 12:59:10>>662 の質問は >>664 で解決してる。解決報告は >>666
質問の解決後に >>667 の Perl厨が余計なことを言い出した。
それに対する反論として >>675 が書かれただけ。
Perl厨はきっと今ごろ赤面w
0679名無しさん@お腹いっぱい。
2010/09/07(火) 14:21:26そうか?
別に深く追求しないで
「単純に時間を計って比べてみな」ってだけなんだから
「現状が速いです」で済む話なんだが?
0680名無しさん@お腹いっぱい。
2010/09/07(火) 15:07:59なんで、ここもプログラムにしないの?
普通は、函数化はしてあるだろうから、それを呼び出すようにするだけじゃん。
わざわざシェル経由して、xargsでこねくり回す意味がわからんわ。
完全に情報後出しの下手ないい訳だなw
0681名無しさん@お腹いっぱい。
2010/09/07(火) 15:13:56よくよめ
xargs使うのは、-max-procs=8 を指定したいから。
同時に動くプロセスを常に8個に保った状態で回したい。
これはFortranだけではできない。
-max-procs=8については最初の質問の >>664 に書かれている。
全く持って「後出しではない」
0682名無しさん@お腹いっぱい。
2010/09/07(火) 15:17:44>普通は、函数化はしてあるだろうから、それを呼び出すようにするだけじゃん。
↑
それを呼び出すようにするだけだとシングルスレッドにしかならないよ。
8スレッド使いたいという質問だったのでは?
0683名無しさん@お腹いっぱい。
2010/09/07(火) 15:43:23と、言ってると思うんだが?
>>これはFortranだけではできない。
数値計算の並列化なんて、Fortranの最も得意とするところじゃん。
0684名無しさん@お腹いっぱい。
2010/09/07(火) 15:44:00特定のパラーメータ振ったデータを生成して、fortranの解析プログラムを起動する
スクリプトなんだろ。そもそもそういう解析プログラムはコマーシャルソフトや別
部門が作ったソフトの場合が多く、それを呼び出すようになど出来ない場合が多い。
他にも、解析プログラムに、汎用でない特定の用途のパラメータ振りを組み込む事
は嬉しくないから、スクリプトで対応する可能性もある。
>>662を読んでその程度を推測できないアマチュアはネチネチと絡むんじゃねーよ。
0685名無しさん@お腹いっぱい。
2010/09/07(火) 16:21:55>>これはFortranだけではできない。
>数値計算の並列化なんて、Fortranの最も得意とするところじゃん。
話をすり替えてはイカン。
数値計算の並列化の話ではなくて、
既存の複数のFortranプログラムを「プロセスをちょうど8個に保ったまま並列起動」したい
という話。
0686名無しさん@お腹いっぱい。
2010/09/10(金) 07:17:49分けたいのですけど、お勧めの方法はなんでしょうか?
0687名無しさん@お腹いっぱい。
2010/09/10(金) 07:24:23普通にバックスラッシュで改行すればいい。
「バックスラッシュ+改行」は消えてなくなって代入される
0688名無しさん@お腹いっぱい。
2010/09/10(金) 08:46:11つまり
declare str="xxx"\
"yyy"\
"zzz"
ということですか。
ちょっと見辛いのですよね。
他にありませんでしょうか?
C++だと
declare str="xxx"\
"yyy"\
"zzz"
のように書けるのですが。
0689名無しさん@お腹いっぱい。
2010/09/10(金) 09:30:34こんな馬鹿もプログラマーなのか?
0690名無しさん@お腹いっぱい。
2010/09/10(金) 09:30:45おいおい、C/C++ならそんなことしなくても、
str = "hoge"
"boke"
"aho";
と書けるだろw
0691名無しさん@お腹いっぱい。
2010/09/10(金) 09:52:25データ上はあくまで1行の文字列を、
文字列が長過ぎる(たとえば100文字以上)だから、
スクリプト上では2行以上にわけて記述したいという話だろ?
だったら、2行目以降はインデントせずに
行頭から記述した方が、前の行からデータが継続していて
実際は1行であることがわかりやすい。
(変にインデントするとスペースやタブや改行がデータに入ってるように誤解する)
よって、>>687 の言う方法で良い。
0692名無しさん@お腹いっぱい。
2010/09/10(金) 09:59:25yyy
zzz"
0693名無しさん@お腹いっぱい。
2010/09/10(金) 10:02:42質問良く良め。それだと改行が入るだろw (質問は >>686 な)
0694名無しさん@お腹いっぱい。
2010/09/10(金) 10:16:11そういうのは最低限LLでやるべきだろ。
実際Perlとかで書いてみて、
シェルスクリプトと比べてみるといいよ。
0695名無しさん@お腹いっぱい。
2010/09/10(金) 10:31:54意地悪ですねw。
>>694
LLってなんですか?
学がなくて申し訳ないです。
0696名無しさん@お腹いっぱい。
2010/09/10(金) 10:35:470697名無しさん@お腹いっぱい。
2010/09/10(金) 11:23:06スクリプトで取得したいのですが、上手くいきません
$ hoge.sh > log &
とのようにすれば可能なのは理解しているのですが、
$ hoge.sh & > log
を実現したいのです
hage.sh内でhoge.sh &を実行しているのですが、
どちらも改変不可なのでhige.sh->hage.sh->hoge.sh
と呼び出さざるを得ません
コマンドラインからhage.shを実行するとhoge.shの出力が画面上で
得られますが、hige.shから呼び出すと、なにも出力されなくなります
このようなことは可能でしょうか?
0698名無しさん@お腹いっぱい。
2010/09/10(金) 11:39:300700697
2010/09/10(金) 14:52:39どうも出力がバッファリングされているようで、
hoge.sh終了までファイルに書き込まれません
ぐぐるとsttyで制御するようなので
stty raw; ( hoge.sh & ) > log ; stty sane; tail -f log
とか
( stty raw ; hoge.sh & ) > log ; stty sane; tail -f log
とかやってみましたが、バッファリングが止まりません
解決するための設定・コマンドはありますでしょうか?
0701名無しさん@お腹いっぱい。
2010/09/10(金) 16:41:21(hoge.sh &) > log
hoge.sh > log &
そもそも、前者によって何を実現したくて、それが何故後者では実現できないのかが分からない。
hage.sh, hoge.shが改変不可で、そのラッパーであるhige.shを作る(のですよね?)、そして
> コマンドラインからhage.shを実行するとhoge.shの出力が画面上で
> 得られますが、hige.shから呼び出すと、なにも出力されなくなります
のようにしたい(のですよね?)って言う話と、最初の話がいまいち繋ってこないんだけど。
ってか
exec > log
hoge.sh &
じゃ駄目なんだろうか?
0702名無しさん@お腹いっぱい。
2010/09/10(金) 16:49:27stty無関係。
仮にhoge.shが下のようなのだと、ちゃんと出てくるはず。
#!/bin/sh
echo 1
sleep 5
echo 2
sleep 5
echo 3
hoge.shの中で動かしているプログラムが端末以外に出力するときに
勝手にバッファリングするようになってるんじゃないか?
0703697
2010/09/10(金) 17:49:17それです!
さらにこの先に、1分間だけ出力ログを監査して問題なければlogoutというのが待っていまして、
そのため第一弾としてログに吐かせようとして、なんだか山にぶつかってたというところです
上手くいけばログをパイプ変更して監査スクリプトに渡すところを作って完了です
土日で終わるといいな。。。
> exec > log
> hoge.sh &
これ、あっさりいけました!
execって引数なしだとリダイレクトなんですね
この使い方初めて知りました
>>702
その通りでした
hoge.shの中でいろいろコマンド呼び出してるんですが、
それがバッファリングしてました
こっちは改変できそうなのでなんとかなりそうです
これで先に進めますm(__)m
0704名無しさん@お腹いっぱい。
2010/09/10(金) 23:52:06> この使い方初めて知りました
シェルの基本ですよ。
ttp://lagendra.s.kanazawa-u.ac.jp/ogurisu/manuals/sh-text/sh/node62.html
他にも以下を知ってることを確認しておくと良いです。
ttp://lagendra.s.kanazawa-u.ac.jp/ogurisu/manuals/sh-text/sh/node31.html
ttp://lagendra.s.kanazawa-u.ac.jp/ogurisu/manuals/sh-text/sh/node40.html
ttp://lagendra.s.kanazawa-u.ac.jp/ogurisu/manuals/sh-text/sh/node64.html
ttp://lagendra.s.kanazawa-u.ac.jp/ogurisu/manuals/sh-text/sh/node65.html
ttp://lagendra.s.kanazawa-u.ac.jp/ogurisu/manuals/sh-text/sh/node66.html
また、時間があるときにでも、全部読んでおくべきです。
ttp://lagendra.s.kanazawa-u.ac.jp/ogurisu/manuals/sh-text/sh/sh.html
0705名無しさん@お腹いっぱい。
2010/09/11(土) 00:02:240706名無しさん@お腹いっぱい。
2010/09/12(日) 04:53:07例えば、
===============
VAR1="ABC"
VAR2="DEF"
VAR3="GHI"
AAA1="VAR1"
AAA2="VAR2"
AAA3="VAR3"
===============
として、通常であれば、$VAR1・$VAR2・$VAR3となると思うのですが、
これをAAA1〜3の値を変数名としてfor文で「$i」使用してVAR1〜3の値を参照したいのです。
よろしくお願い致します。
0707706
2010/09/12(日) 04:55:330708名無しさん@お腹いっぱい。
2010/09/12(日) 05:16:42for i in AAA1 AAA2 AAA3;
do
i=${!i}
echo ${!i}
done
かな。もちろん/bin/shでは動かないけど。
0709名無しさん@お腹いっぱい。
2010/09/12(日) 06:45:55bash依存じゃなくてできる。(純正/bin/shでも動く)
↓
VAR1="ABC"
VAR2="DEF"
VAR3="GHI"
AAA1="VAR1"
AAA2="VAR2"
AAA3="VAR3"
for i in AAA1 AAA2 AAA3
do
eval echo '$'$i
done
0710名無しさん@お腹いっぱい。
2010/09/12(日) 06:53:482重間接だよ。もう1段 evalが必要。
eval eval echo '"$"''$'$i
0711名無しさん@お腹いっぱい。
2010/09/12(日) 20:32:49実際Perlとかで書いてみて、
シェルスクリプトと比べてみるといいよ。
0712名無しさん@お腹いっぱい。
2010/09/12(日) 21:26:47つまらん。やめとけ。
0713697
2010/09/13(月) 18:49:51http://www.edu.ics.saitama-u.ac.jp/~j0114ky/first/html_enshu/10.4.html
のタイムアウト処理を実行したところlinuxで動きませんでした
http://www.nurs.or.jp/~sug/soft/super/bash.htm#sec7
の例も動かず、二日悩んでsolaris10で動かすとちゃんと動く
bashのバージョン違いで挙動が変わるのかと思いつつ、
/bin/配下を眺めてると/bin/bshを発見、あっさり動きました。。。
あんまりこういう使い方はしないと思いますが備忘録的に残しておきます
>>704
ありがとうございます
shはrcを眺めて覚えたんですが、一度はちゃんと仕様から勉強するべきですね
0714名無しさん@お腹いっぱい。
2010/09/13(月) 19:00:50せっかく bashがあるんならもっとスマートにタイムアウト処理できるよ。
こっちがお勧め(5秒待ちの例)
↓
read -t 5 hoge
0715名無しさん@お腹いっぱい。
2010/09/14(火) 00:20:51参考になったぜ。thx!
0716名無しさん@お腹いっぱい。
2010/09/14(火) 22:11:42e.g. 200909 -> 20090931 & 20090831
date -d "1 month 1 day ago YYYYMMDD"でいけると思っていましたが、
「-dなんてネーよバーカ」とSunOSに怒られました。
閏年を考慮しない方法で無理矢理書きはしましたが、
なにかスマートな方法があればお教え下さい。
0717名無しさん@お腹いっぱい。
2010/09/14(火) 22:13:370718名無しさん@お腹いっぱい。
2010/09/14(火) 22:40:14YYYYMM=200909
date -j -v+1m -v1d -v-1d ${YYYYMM}010000 +%Y%m%d
date -j -v1d -v-1d ${YYYYMM}010000 +%Y%m%d
-v1dは冗長かも
0719名無しさん@お腹いっぱい。
2010/09/14(火) 22:47:26FreeBSDの話なんかしてねーよ
0720名無しさん@お腹いっぱい。
2010/09/14(火) 22:53:400721716
2010/09/14(火) 22:55:40そんなべんりーなオプションはなく、
ttp://docs.sun.com/app/docs/doc/819-1210/date-1?l=en&n=1&a=view
こんな感じのオプションしかなかったです
0722716
2010/09/14(火) 23:00:17その処理だけPerlで書いて外部コマンドとして呼ぶことも候補には入れていますが
やっぱりできればシェルスクリプトで書きたいと思っていました。
(モジュールを追加できないので標準モジュールでどこまでできるかも不明ですし)
0723名無しさん@お腹いっぱい。
2010/09/14(火) 23:02:28if文とexprのいい練習課題だね
0724名無しさん@お腹いっぱい。
2010/09/14(火) 23:05:27実際Perlとかで書いてみて、
シェルスクリプトと比べてみるといいよ。
0725名無しさん@お腹いっぱい。
2010/09/14(火) 23:08:23とマジレステスト
0726名無しさん@お腹いっぱい。
2010/09/14(火) 23:08:54だから >>723 が言うような if や expr では解決しない。
Solarisのdateで現在時刻以外を指定するのに、
環境変数TZをいじって 24時間を超える大きなタイムゾーンを捏造するという
裏技があるが、そういう変な方法しかない。
0727名無しさん@お腹いっぱい。
2010/09/14(火) 23:12:17>>723 は date自体を使わずに、日付の数値を自分で計算しろと言ってるのでは?
0728名無しさん@お腹いっぱい。
2010/09/14(火) 23:54:360729名無しさん@お腹いっぱい。
2010/09/15(水) 00:04:20set `cal 8 2010`; shift `expr $# - 1`; echo $1
0730名無しさん@お腹いっぱい。
2010/09/15(水) 01:02:19おもしろいやり方してるな。
俺は普通にgrepとtailとsedあたりでやることを考えてしまうんで、ちょっと新鮮だ。
0731名無しさん@お腹いっぱい。
2010/09/15(水) 01:07:27cal 8 2010 | tr -s ' ' '¥012' | sed -n '$p'
0732名無しさん@お腹いっぱい。
2010/09/15(水) 01:23:18Solaris 10, Ubuntu 10.04はokだった。
0733名無しさん@お腹いっぱい。
2010/09/15(水) 02:32:21arg配列のそんな使い方があったのか。 自分が思いつくのは普通の
配列だな。
$ DAYS=(`cal 8 2010`); echo ${DAYS[`expr ${#DAYS[*]} - 1`]}
0734名無しさん@お腹いっぱい。
2010/09/15(水) 16:35:01./example | while read x
do
なんか処理して変数代入とか
done
変数を利用して後処理
というのをパイプ(サブシェル)を使わずにできない?
変数相当の値を一旦外部ファイルに書き出さないと駄目かな
exampleの出力を自身の入力にできるといいんだけど
0735名無しさん@お腹いっぱい。
2010/09/15(水) 16:51:27RESULT=`./example | while read x
do
なんか処理して echo 処理結果
done`
"$RESULT" を利用して後処理
0736名無しさん@お腹いっぱい。
2010/09/15(水) 17:44:06のようにすれば、while の外に出ても {} の内側にいるかぎりは変数の値が見える。
以下のようにすればそもそもサブシェルが生成されないが、
何やってるのかひじょーにわかりにくいのでオススメはしない。
while read x; do ... done <<_EOF_
`./example`
_EOF_
bash 限定。
while read x; do ... done <<<"`./example`"
0737名無しさん@お腹いっぱい。
2010/09/15(水) 19:46:27[ -z "$HOGE" ] && { ./example | HOGE=hage exec $0; }
while read x; do
なんか処理して echo 処理結果
done
0738716
2010/09/16(木) 01:30:00UNIXを初めて触ったころには使っていましたが、
それ以来一切関わることなく脳内から完全に抜け落ちていました。
cal出力の最後を月末とすることでうまくいきそうです。
レスくれた方ありがとうございました!
0739名無しさん@お腹いっぱい。
2010/09/16(木) 19:10:11斯界のおっさんたちは皆一度は試してるんだぞぉ
0741名無しさん@お腹いっぱい。
2010/09/16(木) 19:23:19ネタで書いてると思ったよ。
0742名無しさん@お腹いっぱい。
2010/09/17(金) 07:42:060743名無しさん@お腹いっぱい。
2010/09/17(金) 08:09:55FreeBSDの/bin/shで、>>737 動かないよ。
たしかにFreeBSDはヘボだな。
0744名無しさん@お腹いっぱい。
2010/09/17(金) 08:31:55[ -z "$HOGE" ] && { ./example | HOGE=hage $0; exit; }
0745名無しさん@お腹いっぱい。
2010/09/17(金) 08:41:25わざわざこんなことしなくても、
command | while ... がサブシェルにならないから、
最初から command | while ... と書けばいいんだな。
よって、>>737 は全然解決になってない。
0746名無しさん@お腹いっぱい。
2010/09/17(金) 08:51:570747名無しさん@お腹いっぱい。
2010/09/17(金) 09:09:000748名無しさん@お腹いっぱい。
2010/09/17(金) 09:15:550749名無しさん@お腹いっぱい。
2010/09/17(金) 09:18:43同じサブシェル問題だと、後付けで気付いたのはお前の方だろw
俺は最初からわかってたよ。
0750名無しさん@お腹いっぱい。
2010/09/17(金) 09:22:05> 俺は最初からわかってたよ。
> 俺は最初からわかってたよ。
> 俺は最初からわかってたよ。
> 俺は最初からわかってたよ。
0751名無しさん@お腹いっぱい。
2010/09/17(金) 09:36:12>>742 >どんなヘボシェルだよ。ww
↑って書いてる時点で 742 はサブシェル問題だと気付いてないよね。
FreeBSDだけじゃなく、フツーのbourne shでは動かないことに
この時点でまだ気づいてないww
0752名無しさん@お腹いっぱい。
2010/09/17(金) 09:38:58> 俺は最初からわかってたよ。
と言いたいのだったら最初から書くべきだったな。ww
0753名無しさん@お腹いっぱい。
2010/09/17(金) 09:43:14最初からわかってたのは本当だ。
でも答を書いてしまうと面白くないから >>737 他の反応を見るために書かなかった。
「ネタで書いてると思ったよ」という言葉に、
「サブシェル問題の解決なのにサブシェル問題に引っかかってるという笑いネタかw」
というニュアンスを含ませたつもりだが、読みとれなかったかい?
0754名無しさん@お腹いっぱい。
2010/09/17(金) 09:45:100755名無しさん@お腹いっぱい。
2010/09/17(金) 09:48:05>>737 自身が 737 を書いた時点で、
「全然問題の解決になってない」ということを理解していなかったということだ。
これだけは紛れもない事実。
0756名無しさん@お腹いっぱい。
2010/09/17(金) 09:52:19> 俺は最初からわかってたよ。
と、>>741が後付けで必死に言い張っている事。
0757名無しさん@お腹いっぱい。
2010/09/17(金) 09:54:04741 をいくら叩いても >>737 の恥ずかしさを弁解できないことは理解してますか?
0758名無しさん@お腹いっぱい。
2010/09/17(金) 09:56:580759名無しさん@お腹いっぱい。
2010/09/17(金) 10:10:47バグはそんなに恥ずかしくない。後付けで↓と言い張るよりは。
> 俺は最初からわかってたよ。
> 俺は最初からわかってたよ。
> 俺は最初からわかってたよ。
> 俺は最初からわかってたよ。
0760名無しさん@お腹いっぱい。
2010/09/17(金) 10:20:59じゃあ、バグを認めずに(バグの原因を理解せずに)
>>742 「どんなヘボシェルだよ。ww」
って言うのはどれくらい恥ずかしいですか?
0761名無しさん@お腹いっぱい。
2010/09/17(金) 10:39:200762名無しさん@お腹いっぱい。
2010/09/17(金) 10:42:05それとも、/bin/sh -> zsh みたいにリンクされたOS使ってたのか?
0763名無しさん@お腹いっぱい。
2010/09/17(金) 11:51:220764名無しさん@お腹いっぱい。
2010/09/17(金) 11:59:58で、762の質問への回答は?
(1)動作確認してなかったのか、(2)/bin/sh -> zsh にしてたのか?(その場合はOS名も)
0766名無しさん@お腹いっぱい。
2010/09/17(金) 17:57:23>確認してないが何か?
>確認してないが何か?
>確認してないが何か?
>確認してないが何か?
あーあ。自爆、敗北宣言乙w
0767名無しさん@お腹いっぱい。
2010/09/17(金) 18:01:20どこが敗北宣言なんだろう。ww
■ このスレッドは過去ログ倉庫に格納されています