シェルスクリプト総合 その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
0769名無しさん@お腹いっぱい。
2010/09/18(土) 00:43:05dash on Debian だと
40 70 10 0
てなったよ。
set -x
してみたらどう?
0770名無しさん@お腹いっぱい。
2010/09/18(土) 00:58:52改行コードが CR+LF になってるだろ。LFのみにしろ。
var1=100^M とかになって実行されるから、正しく数値として実行されない。
0771名無しさん@お腹いっぱい。
2010/09/18(土) 01:17:44御回答、ありがとうございます。
set -x var1=100
set -x var2=0
としましたところ、今度は下記の結果が出力されました。
$ sh test02.sh
+ set -x $'var2=0\r'
++ expr 10 + 30
+ num1=$'40\r'
++ expr - 30
expr: syntax error
+ num2=$'\r'
++ expr 100 % 30
+ num3=$'10\r'
++ expr
expr: missing operand
Try `expr --help' for more information.
+ num4=$'\r'
+ echo $'40\r' $'\r' $'10\r' $'\r\r'
10
>>769
御回答、ありがとうございます。
Meadowにて改行コードをLFのみにしようとしたのですが、メニューが英語で、
どこを触ればいいのか分かりませんでした…
メニューを日本語化できないかと検索してみたのですが、403エラーでサイトに
入ることが出来ませんでした。
質問ばかりで恐縮ですが、LFのみにする為、どこを触ればよいか教えていただけないでしょうか?
0772名無しさん@お腹いっぱい。
2010/09/18(土) 01:28:30改行コードの問題ということがはっきりして、
このスレ的には問題解決したので、
次の方どうぞ
↓
0773名無しさん@お腹いっぱい。
2010/09/18(土) 01:33:31$ tr -d '\r' < in > out
あと、 set の使い方が違うよ。man 見てね。
0774名無しさん@お腹いっぱい。
2010/09/18(土) 01:37:53C-x RET f
で, sjis-unix とか指定すればいい。
分からなかったら禿丸とかでも改行コード変更できるだろ。
0775名無しさん@お腹いっぱい。
2010/09/18(土) 01:52:090776名無しさん@お腹いっぱい。
2010/09/18(土) 08:28:48Don't say "shell", idiot !
あ、こっちは日本語スレだった、、
0777名無しさん@お腹いっぱい。
2010/09/21(火) 17:22:43起動したアプリケーションの終了を待たずに、次のステップを実行するにはどう書けばいいのですか?
0778名無しさん@お腹いっぱい。
2010/09/21(火) 17:34:570779名無しさん@お腹いっぱい。
2010/09/21(火) 17:50:040780名無しさん@お腹いっぱい。
2010/09/25(土) 08:13:01・ findで見付かったファイルに対してそれぞれ複数のコマンドが必要な処理を行いたい
・ ディレクトリ名にスペースが含まれる可能性がある
・ 複数コマンドと言っても mv $f $f.org;sed -e '....' <$f.org >$f;rm $f.org みたいなワンライナーな処理で
汎用的に使いまわすようなものでも無い。
以上の条件をふまえると、思い付くやり方は
1. 複数のコマンド部分をシェルスクリプトにして、find -exec
2. 複数のコマンド部分をシェルスクリプトにして、find -print0 |xargs -0
3. 一時的にIFS='\n'にして、for f in `find ...`;do ....
という3つが思い付くんですが、1,2はわざわざスクリプトにするのは億劫で、3はちょっとトリッキーな感じで
どれもしっくり来ません。
割と良くある処理だと思うんですが、標準的なやり方って他に何かありませんかね?
0781名無しさん@お腹いっぱい。
2010/09/25(土) 09:14:000782名無しさん@お腹いっぱい。
2010/09/25(土) 10:01:27一列目に日付が二列目に数字が入っているのですが
fileAにない日付のデータがfileBにはあります。
fileAになければfileBのデータを補完して新たなfileを作成したいのですが、
簡単な方法ありますでしょうか?
file A
199901 10
199902 15
199903 16
199004 17
file B
199901 18
199902 13
199903 13
199004 13
199005 18
file NEW
199901 10
199902 15
199903 16
199004 17
199005 18
というようにしたいのですがどうすればよいでしょうか。
0783名無しさん@お腹いっぱい。
2010/09/25(土) 10:31:02$ sort -u -k 1,1 filea fileb
199004 17
199005 18
199901 10
199902 15
199903 16
0784名無しさん@お腹いっぱい。
2010/09/25(土) 12:01:48それはちょっと面倒だなぁ。
0785名無しさん@お腹いっぱい。
2010/09/25(土) 12:07:30-exec sh -c 'f="{}"; mv "$f" "$f.org";sed -e ... < "$f.org" > "$f";rm "$f.org"'
0786名無しさん@お腹いっぱい。
2010/09/25(土) 13:17:19それはもっと面倒だなぁ。
0787名無しさん@お腹いっぱい。
2010/09/25(土) 13:42:32タイプ数増やして応用力とはこれ如何にw
findで見つかったファイル名の中に $ を含むもの( $hoge という名前のファイルとか)
があったら、f="{}" のところで展開されちゃうから、エンバグしてるじゃん。
0788名無しさん@お腹いっぱい。
2010/09/25(土) 14:11:13そのバグは >>781 に既に含まれてるから、「エンバグ」ではない。
あと、$だけじゃなくて " ` とかがあってもコケるな。
0789名無しさん@お腹いっぱい。
2010/09/25(土) 14:27:21ありがとうございます!
試してみます!
0790名無しさん@お腹いっぱい。
2010/09/26(日) 19:42:22出力順を変えない方法もあるよ:
$ cat file_A file_B | awk '!a[$1]++'
0791名無しさん@お腹いっぱい。
2010/09/26(日) 20:09:55dpkg -x xxx.deb xxx
するスクリプトを作りたいんですが、
xxx.deb から .debを削除するには?
0792名無しさん@お腹いっぱい。
2010/09/26(日) 21:08:350793791
2010/09/26(日) 22:09:55sedを使うのかと思ってました。
basenameってこう言う使い方ができたんですね。
ありがとうございました。
0794名無しさん@お腹いっぱい。
2010/09/27(月) 00:00:54普通は、
for f in *.deb;do dpkg -x $f ${f%.deb};done
だけどな。
0795793
2010/09/27(月) 06:55:47おー スマートですね
0796名無しさん@お腹いっぱい
2010/09/29(水) 18:50:18PROC=`ps ax | grep "process"`
if [ -n "$PROC" ]
then
として見たら、grep processがあるからダメなのね
どうすりゃいいの?
0797名無しさん@お腹いっぱい。
2010/09/29(水) 18:54:03pgrepないの?
0798名無しさん@お腹いっぱい。
2010/09/29(水) 18:55:070799名無しさん@お腹いっぱい。
2010/09/29(水) 18:56:12見たいプロセスが logreport.sh とかだった場合に困る。
0800名無しさん@お腹いっぱい。
2010/09/29(水) 19:00:160801名無しさん@お腹いっぱい。
2010/09/29(水) 19:03:33ない環境ならしょうがないけど。
0802名無しさん@お腹いっぱい。
2010/09/29(水) 20:45:17そりゃ、PerlやRuby、Pythonなどが普及しても
「どこでも通じるからawkは覚えておいたほうがいい」なんてのがUNIX文化。
そこにおいて >801 は異質に見える。
0803名無しさん@お腹いっぱい。
2010/09/29(水) 20:48:450804名無しさん@お腹いっぱい。
2010/09/29(水) 20:52:30必死だな。
0805名無しさん@お腹いっぱい。
2010/09/29(水) 20:53:030806名無しさん@お腹いっぱい。
2010/09/29(水) 21:10:000807名無しさん@お腹いっぱい
2010/09/29(水) 21:15:56pgrepは使えませんでした
で、板が代わって、そういう小技こねくりまわした方法が見れない
もう一度、書いてもらえる雰囲気じゃない?
0808名無しさん@お腹いっぱい。
2010/09/29(水) 21:23:480809名無しさん@お腹いっぱい。
2010/09/29(水) 21:23:54いまいじっているシステムは全部で16Mぐらいの/
だけど、awkはある。pgrepはない。
perlもpythonもbashもない。
こういうシステム上でもinitスクリプト等にawkは必須。
0810名無しさん@お腹いっぱい。
2010/09/29(水) 21:24:54必死な屁理屈野郎にはなに言っても無駄だと思うよ。
0811名無しさん@お腹いっぱい。
2010/09/29(水) 21:59:51実際Perlとかで書いてみて、
シェルスクリプトと比べてみるといいよ。
0812名無しさん@お腹いっぱい。
2010/09/29(水) 22:03:17>>800が定石だと思う.
0813807
2010/09/29(水) 22:15:12ありがとう
0814名無しさん@お腹いっぱい。
2010/09/30(木) 00:48:340815名無しさん@お腹いっぱい。
2010/09/30(木) 10:48:540816名無しさん@お腹いっぱい。
2010/09/30(木) 18:11:46このスクリプトをcrondで1時間ごとに起動する
1度メールすると次は送らない
とするなると、メールを送ったかどうかの、何らかのフラグが必要でけど
一般的には、何をフラグとすればいいでしょうか?
ファイルの有無?
ファイルの中身の有無としたとき、ファイルのテキストを空にするコマンド
ってありました。?
0817名無しさん@お腹いっぱい。
2010/09/30(木) 18:16:590818名無しさん@お腹いっぱい。
2010/09/30(木) 18:18:11> 1度メールすると次は送らない
生涯で1回しかメール送らないってこと?
> ファイルの中身の有無としたとき、ファイルのテキストを空にするコマンド
> ってありました。?
:>file みたいな
0819名無しさん@お腹いっぱい。
2010/09/30(木) 18:37:44>>818
コロンが無駄です
0820名無しさん@お腹いっぱい。
2010/09/30(木) 18:53:06サンキュー
0821名無しさん@お腹いっぱい。
2010/09/30(木) 19:13:37どこでも動く :> の方が安心といえば安心。
まあ、sh と zsh をごっちゃにする人はあんまりいないと思うけど。
0822名無しさん@お腹いっぱい。
2010/09/30(木) 22:01:22':' って初めて知ったが他にどんな使い方があるのなか?
0823名無しさん@お腹いっぱい。
2010/09/30(木) 22:03:020824名無しさん@お腹いっぱい。
2010/09/30(木) 22:05:11: ${FOO:=bar} で変数のデフォルト値設定とかか?
0825名無しさん@お腹いっぱい。
2010/09/30(木) 22:44:52は俺だけか?
0826名無しさん@お腹いっぱい。
2010/09/30(木) 22:46:070827名無しさん@お腹いっぱい。
2010/09/30(木) 22:53:06そっちの方が、誰が見てもわかりやすいってのはあるがな。
0828名無しさん@お腹いっぱい。
2010/09/30(木) 23:10:03if 肯定の条件;
:
else
本来やりたいこと
fi
みたいなの書いたことがある。
0829名無しさん@お腹いっぱい。
2010/10/01(金) 00:38:180830名無しさん@お腹いっぱい。
2010/10/01(金) 01:02:16if ! ( 肯定の条件 );
本来やりたいこと
fi
じゃだめ?
0831名無しさん@お腹いっぱい。
2010/10/01(金) 06:13:44純正シェルで動かない
0832名無しさん@お腹いっぱい。
2010/10/01(金) 10:44:57複数行のコメント
_
0833名無しさん@お腹いっぱい。
2010/10/01(金) 10:54:38それもコロンが無駄です
0834名無しさん@お腹いっぱい。
2010/10/01(金) 13:34:00完全なコメントアウトになってないのが問題だな。
0835名無しさん@お腹いっぱい。
2010/10/02(土) 18:57:00Linux bash3.2.25 の環境です
関数がいくつかあって、ある関数内(Aとします)の条件式(if)で分岐した結果、異なる関数(Bとします)を
呼び出したとします。
その呼び出された関数Bの処理が終わった後、直前に実行してた関数Aに戻る方法はないでしょうか?
何をしたいかというと、Aで実行したコマンドの結果の判定を行い正だった場合に
関数Bに移動してそこでwhileを使ってカウンタを増やし、また関数Aに戻ってコマンドを実行し
偽になるまで繰り返したいのです。(偽になったら関数A内のif文で抜けて次の関数Cへと進みます)
どなたか良い方法を教えていただけると助かります
0836名無しさん@お腹いっぱい。
2010/10/02(土) 19:02:53関数というのは、処理が終れば呼び出し元に戻る。
だから何もしなくても関数Aに戻るよ。
逆に、関数A「以外」に戻ることはできない。
0837名無しさん@お腹いっぱい。
2010/10/02(土) 19:08:25わぁ、すみません・・・
仰る通りでした。途中で別の所を呼んでたのをすっかり忘れておりました。
お手数おかけしました・・・
0838名無しさん@お腹いっぱい。
2010/10/04(月) 15:12:520839名無しさん@お腹いっぱい。
2010/10/04(月) 16:19:30別にLinux依存の質問じゃないし、こっちで聞いていいよ。
あと、Linux板のシェルスクリプトスレは落ちて終了したから、こっちで聞くしかない。
0840名無しさん@お腹いっぱい。
2010/10/04(月) 16:43:160841名無しさん@お腹いっぱい。
2010/10/06(水) 11:17:31./hogehoge >/dev/null 2>&1
とやりますが、なぜリダイレクトは後ろから評価されるのですか?
この順序に例外はありますか?
0842名無しさん@お腹いっぱい。
2010/10/06(水) 11:36:15後ろから評価されてないよ。
2>&1 は 標準エラーを標準出力と同じところに出力するということ。
./hogehoge >/dev/null 2>&1
の場合は 2>&1 が評価された時点で、標準出力が /dev/null に設定されている
ので、標準エラーも /dev/null に設定される。
./hogehoge 2>&1 >/dev/null
この場合は 2>&1 が評価された時点で、標準出力が画面に表示される設定になっ
ているから、標準エラーが画面表示される。
分かり難い説明だと思うので、検索したほうがいいかも。
0843名無しさん@お腹いっぱい。
2010/10/06(水) 11:38:501 >/dev/null 標準出力を/dev/nullにリダイレクトする。
2 2>&1 標準エラーを(さっき/dev/nullにリダイレクトした)標準出力にdupする。
感覚に合わないのは、./hogehoge 2>&1 | hagedebu
これは、標準出力をパイプにリダイレクトするのが先。
0844名無しさん@お腹いっぱい。
2010/10/06(水) 11:43:350845名無しさん@お腹いっぱい。
2010/10/06(水) 11:46:570846名無しさん@お腹いっぱい。
2010/10/06(水) 12:06:42間違いを堂々と書いてるサイトや文章が結構存在するから注意。
正しくは「前から評価される」
「ファイル記述子の複製」を理解すれば理解できる。
0847名無しさん@お腹いっぱい。
2010/10/06(水) 12:19:14正しいかどうかよりもわかりやすさ優先なので。
何か問題でも?
0848名無しさん@お腹いっぱい。
2010/10/06(水) 13:13:08ここでわからないとされるのは、前から評価されるなら
2>&1 で標準エラー出力(2)を標準出力(1)にしたときに
そのあと >/dev/null にしたときに なぜ元標準エラー出力は
釣られないのか というところだろ。
ここを簡潔に説明するのに必要なのはdupの勉強ではない
0849名無しさん@お腹いっぱい。
2010/10/06(水) 14:02:53なんで、マニュアルに書いてあることを無視するん?
0850名無しさん@お腹いっぱい。
2010/10/06(水) 20:27:44>/bin/shプログラミング入門
>ttp://freebooks.info.nara-k.ac.jp/archive/ShellProgramming/?
つぎのスレから、削除するべき。
0851名無しさん@お腹いっぱい。
2010/10/06(水) 20:33:17後ろから評価されるって思うには、どういう風に解釈すればいいの?
普通、2>&1 を「stderrにstdoutと同じにする」って読むと思うけど
これだと、前から後ろに順番に読まないと意味が合わないよね
読み方が違う?もっと根本的なところが違う?
0852名無しさん@お腹いっぱい。
2010/10/06(水) 20:34:18の間違い・・・
0853名無しさん@お腹いっぱい。
2010/10/06(水) 20:54:30として、書き出される順番が揃わなくて考えこんだ日を思い出した
0854名無しさん@お腹いっぱい。
2010/10/06(水) 23:17:59言い直したところでその説明だと致命的におかしいのぜ。
ls -e 2>&1 >hoge.txt
のとき、標準エラー出力はhoge.txtに吐かれない。
「stderrにstdoutと同じにする」 と読んでしまったら
評価順序的にhoge.txtに吐かれないとおかしいだろ。
同じになったんだから。
「同じにする」という理解方法が間違い・
0855名無しさん@お腹いっぱい。
2010/10/07(木) 00:11:24(ハンドルみたいなものかな?)
に対して、stdoutとかstderrは、「ファイル」そのもの。
これらを混同するから、わからなくなるだけ。
>>853
さらに、バファリンが絡んできて、わけわかめ?
0856名無しさん@お腹いっぱい。
2010/10/07(木) 06:40:07>stdoutとかstderrは、「ファイル」そのもの。
↑違うよ。
stdoutとかstderrはそれぞれファイル記述子1と2の別名。
例えば、hoge 2>&1 と、 hoge 2> /dev/stdout は同じ動作。
ファイルそのものはまた別。
0857名無しさん@お腹いっぱい。
2010/10/07(木) 12:22:41「FILEそのもの」と書きたかったのかな。
FILEは「ファイル」じゃなく「ファイルハンドル」
ファイルでスクリプタも、UNIX固有の特殊なファイルハンドル for システムコール。
0858名無しさん@お腹いっぱい。
2010/10/07(木) 14:08:170859名無しさん@お腹いっぱい。
2010/10/07(木) 14:25:35hoge 3>&2 2>&1 1>&3
じゃ駄目?
0860名無しさん@お腹いっぱい。
2010/10/07(木) 14:36:36うまくいった・・・
となると今までの評価順序の話は根底から崩れる予感。
&3 って誰だよって話
0861名無しさん@お腹いっぱい。
2010/10/07(木) 14:38:140862名無しさん@お腹いっぱい。
2010/10/07(木) 14:47:10「後ろから評価される ように 動作する」と考えると、
>>859 で stderrとstdoutを入れ換える動作が説明できない。
0863名無しさん@お腹いっぱい。
2010/10/07(木) 14:50:32> となると今までの評価順序の話は根底から崩れる予感。
> &3 って誰だよって話
最初から全然理解できてないだけじゃん。
0864名無しさん@お腹いっぱい。
2010/10/07(木) 16:46:04説明よろしくお願いします
0865名無しさん@お腹いっぱい。
2010/10/07(木) 17:38:302>&1 : dup2(1,2) 2を1と同じところにつなぐ(3は元の2の先(stderr)のまま)
1>&3 : dup2(3,1) 1を3と同じところにつなぐ(2は元の1の先(stdout)のまま)
0866名無しさん@お腹いっぱい。
2010/10/07(木) 21:44:59見えるのか教えてくれ
0867名無しさん@お腹いっぱい。
2010/10/07(木) 23:06:21自分で考えろよ
0868名無しさん@お腹いっぱい。
2010/10/07(木) 23:13:57■ このスレッドは過去ログ倉庫に格納されています