シェルスクリプト総合 その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
0748名無しさん@お腹いっぱい。
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
0768名無しさん@お腹いっぱい。
2010/09/18(土) 00:37:33シェルスクリプトの練習の為、練習用のシェルスクリプトを作成しており、
Cygwin上にて
#!/bin/sh
var1=100
var2=0
num1=`expr 10 + 30`
num2=`expr $var1 - 30`
num3=`expr 100 % 30`
num4=`expr $var2 && 1000`
echo $num1 $num2 $num3 $num4
という、上記内容のシェルを実行しました。
下記のような結果が出力される予定でした。
$./script2
40 70 10 0
ところが、
expr: non-integer argument
test02.sh: line 7: 1000: command not found
00
という内容が出力されてしまいました。
$var1、$var2が認識されていないようなのですが、原因が分かりません。
シェルはbash、OSはWindowsXPSP3です。
何卒、御教授お願い致します。
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の勉強ではない
■ このスレッドは過去ログ倉庫に格納されています