シェルスクリプト総合 その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
0199名無しさん@お腹いっぱい。
2010/03/30(火) 07:03:23CSVファイルをシェル配列に格納していろいろ加工しようと思っています。
が、CSVに空の項目がある場合に上手く格納できず、空項目を無視してしまいます。
------------ソース-------------
cat ${file} | while read line
eval ARRAY="(`cat ${line} | awk {'print $1,$2,$3'}`)"
→以降ARRAYを加工
----------ソースここまで---------
これを実行すると
AAA,BBB,CCC →ARRAY[0] =AAA,ARRAY[1] =BBB,ARRAY[2] =CCC
⇒ 想定通り
,BBB,CCC →ARRAY[0] =BBB,ARRAY[1] =CCC
⇒ ARRAY[0]=””,ARRAY[1] =BBB,ARRAY[2] =CCCにしたい
何か工夫が必要なんでしょうか?
0200199
2010/03/30(火) 07:28:56× awk {'print $1,$2,$3'}
○ awk -F , {'print $1,$2,$3'}
0201名無しさん@お腹いっぱい。
2010/03/30(火) 08:29:01#!/bin/bash
file=hoge.csv
cat ${file} | while IFS=, read ARRAY[0] ARRAY[1] ARRAY[2]; do
echo 0: ${ARRAY[0]}
echo 1: ${ARRAY[1]}
echo 2: ${ARRAY[2]}
done
0202名無しさん@お腹いっぱい。
2010/03/30(火) 21:39:41IFSって上書きした時の影響範囲ってスクリプト内だけなんですね…全体だと思ってました。
教えていただいたソースで実現できました。
ありがとうございます。
が、もう一度処理を見直した結果、ARRAYの加工と同時に元の${line}も使用するので、
一度lineに格納してから改めてARRAYに分割・格納する必要があることが分かりました。
条件が後出しになってしまって申し訳ありませんが、何か方法はないでしょうか?
0203名無しさん@お腹いっぱい。
2010/03/31(水) 01:35:390204名無しさん@お腹いっぱい。
2010/04/01(木) 06:57:16setを使ってみましたが上手くいかず…
ARRAY=`set - ${line}`
でいけるんですか?
0205名無しさん@お腹いっぱい。
2010/04/01(木) 09:17:38set は $1 $2 $3 ... に値をセットする。
0206名無しさん@お腹いっぱい。
2010/04/01(木) 11:45:07つられちゃったw てへっ?☆
0207名無しさん@お腹いっぱい。
2010/04/01(木) 19:42:04line=',aaa,bbb'
IFS=,
ARRAY=($line)
0208名無しさん@お腹いっぱい。
2010/04/08(木) 06:05:00./a &
./b
これだと、2つめのジョブの終了は待ちますが、1つめはまだバックグランドで実行されている可能性が出てしまいます
0209名無しさん@お腹いっぱい。
2010/04/08(木) 06:19:10./b
wait
0210名無しさん@お腹いっぱい。
2010/04/08(木) 06:41:22./a &
./b &
wait
0211名無しさん@お腹いっぱい。
2010/04/08(木) 09:57:16まじ?
0212名無しさん@お腹いっぱい。
2010/04/08(木) 10:03:250213名無しさん@お腹いっぱい。
2010/04/08(木) 22:52:39前スレか前々スレに確かそんな話題があった
0214名無しさん@お腹いっぱい。
2010/04/28(水) 14:12:30シェルスクリプト(bash)内で、非同期で他のシェルを呼び出したり、
javaコマンドを実行したりしたいのですが、どのように書けばよいのでしょうか。
(戻り値は必要無いです。)
0215名無しさん@お腹いっぱい。
2010/04/28(水) 14:12:540216名無しさん@お腹いっぱい。
2010/04/28(水) 14:29:50bashのmanpageみたら確認できました。
(非同期、で検索してたので見落としてました。)
ありがとうございます。
0217名無しさん@お腹いっぱい。
2010/05/05(水) 04:29:57if文で以下、括弧の違いを教えてくれませんか?
ぐぐっても分からなかった・・・
2重も1重も同じとおもってよいのでしょうか?
if [[ xxxx ]];then
if [ xxxx ];then
0218名無しさん@お腹いっぱい。
2010/05/05(水) 05:17:13シェルスクリプトの中で、
ls /honya/* >> list.txt をしたファイル名使いたいのですが、
Directory や Filenameにメタキャラやらスペースがいっぱい
あります。そんなの作るなって言えれば、いいのですが、ユーザ
さんは、Windowsだし。見てるとそれなりに規則性があって
運用してるんだなってわかります。
話がそれましたが、シェルの中での処理を教えて下さい。
よろしくお願いします。
0219名無しさん@お腹いっぱい。
2010/05/05(水) 07:05:17[[ hoge -a boke ]] は文法エラー
[[ hoge && boke ]] と書く
[ hoge && boke ] は文法エラー
[ hoge -a boke ] と書く
-o と || についても同様。
[[ hoge = h* ]] は真
[ hoge = h* ] は偽(ただしカレントディレクトリにhogeというファイルがあると真)
0220名無しさん@お腹いっぱい。
2010/05/05(水) 07:15:24ファイル名に改行コードが含まれていないなら、
ls /honya/* >> list.txt
while IFS= read -r hoge
do
echo "$hoge"
done < list.txt
の形で処理できる(メタキャラやらスペースもOK)
変数を参照する時には "$hoge" のように必ず " " を付けること。
0221名無しさん@お腹いっぱい。
2010/05/05(水) 08:25:45ありがとうございます。さすがです。
読み込んだファイルを sed か tr 一つづつ 変換して書き出すしか
ないかなぁって思ってました。
こんな方法があるのですね。勉強させていただきました。
0222名無しさん@お腹いっぱい。
2010/05/05(水) 09:29:01>>220のようにlsの結果を使うのは素人。↓こういう仮定を勝手に設定してはいけない。
> ファイル名に改行コードが含まれていないなら、
for fname in /honya/*;do echo "$fname";done
が正しい。
0223名無しさん@お腹いっぱい。
2010/05/05(水) 09:38:47おまえ、もっとアホ
それではファイル名のスペースがもろに分離されてしまって
全く動作しない。
まあ、釣りだろうけど
0224名無しさん@お腹いっぱい。
2010/05/05(水) 09:41:43質問自体が、
「lsの結果のファイルがすでにあって、それを処理するスクリプトが欲しい」
ということなのだから、lsの結果を使うことまでは「前提条件」かと。
0225名無しさん@お腹いっぱい。
2010/05/05(水) 10:55:07分離されねーよ。
恥をかきにのこのこ出てきて… これほどのバカはめったにいない。
>>224
ダメな前提の質問なのだから、正しく処理するスクリプトを作成する事は不可能。が正解。
0226名無しさん@お腹いっぱい。
2010/05/05(水) 11:39:49笑殺させられたくないから、もうひとつ先に言っといてやる。
「ARG_MAX超えたら動作しない」とか言い出すなよ。
確実に5人は笑い死にするぞ。
0227名無しさん@お腹いっぱい。
2010/05/05(水) 13:21:18ありがとうございます。
括弧の数によって、&&や-aの使い方が変わるのですね。
一般的には、二重括弧でよいのでしょうか?
0228名無しさん@お腹いっぱい。
2010/05/05(水) 13:27:30一般的には [ ] の方が良い。
[[ ]] は互換性がないので使わない方がよい。
0229名無しさん@お腹いっぱい。
2010/05/05(水) 18:09:03僕の質問が悪くて、申し訳ありません。
取り敢えず、シェルは完成して、今テスト中です。
結局、シェルの中で、Find -type f して、コマンドに
渡しました。
ここにアップしたら、見てもらえるかなぁなんて都合
良すぎ?
エラー処理とか全然してないんですが・・・。
0230名無しさん@お腹いっぱい。
2010/05/05(水) 18:18:340231名無しさん@お腹いっぱい。
2010/05/05(水) 21:51:50人のことくずとか言うな。
何様?
0232名無しさん@お腹いっぱい。
2010/05/05(水) 21:54:430233名無しさん@お腹いっぱい。
2010/05/05(水) 22:26:27引っ込んでろ。クズ。
0234名無しさん@お腹いっぱい。
2010/05/05(水) 22:36:54おまえさぁ、ここUnix板だぜ。
技術系の板で、あほか。
0235名無しさん@お腹いっぱい。
2010/05/05(水) 22:42:520236名無しさん@お腹いっぱい。
2010/05/05(水) 23:10:59意味不明。引っ込んでろ。クズ。
0237名無しさん@お腹いっぱい。
2010/05/05(水) 23:21:520238名無しさん@お腹いっぱい。
2010/05/06(木) 04:01:37新参乙です(悪いとは言ってない)
さんざんガイシュツ。
ま、ここの人は優しいから俺以外のシッタカが教えてくれます。
0239名無しさん@お腹いっぱい。
2010/05/06(木) 04:30:310240名無しさん@お腹いっぱい。
2010/05/06(木) 12:25:18ローカルと別のマシン hoge.example.net とで同期したいとします。
#!/bin/sh
cd
rsync -avzu -e ssh {tex,org,.emacs.d,.w3m} hoge.example.net:
rsync -avzu -e ssh hoge.example.net:\{tex,org,.emacs.d,.w3m\} .
とすればできますが、この {tex,org,.emacs.d,.w3m} 部分を1つの変数
export FILES="{tex,org,.emacs.d,.w3m}"
のようにしたいのです。これでは {} が展開されず、そんなファイル名はありませんとなります。
for で回すのも手ですが、rsync を何度も呼び出すことになりコストがかさむため一度のrsyncで行いたいのです。
どのようにすればうまく一つの変数に入れられるでしょうか?
0241名無しさん@お腹いっぱい。
2010/05/06(木) 12:48:380242名無しさん@お腹いっぱい。
2010/05/06(木) 12:50:58普通に空白区切りの変数でいいじゃないか
0243名無しさん@お腹いっぱい。
2010/05/06(木) 13:06:200244名無しさん@お腹いっぱい。
2010/05/06(木) 13:08:32eval
0245名無しさん@お腹いっぱい。
2010/05/06(木) 13:15:37その判断基準だとOpenSolarisも板違いになってしまいますな。
0246名無しさん@お腹いっぱい。
2010/05/06(木) 13:16:010247名無しさん@お腹いっぱい。
2010/05/06(木) 13:17:58OpenSolarisの /bin/sh の正体は ksh93 (Solaris10以前とは違う)
OpenSolarisの bashは /bin/bashで、/bin/shとは別。
0248240
2010/05/06(木) 13:36:52空白区切りだと hoge.example.net:を全てに付与できなさそうなのです。
>>243
wwwwwww
Mac OS XなのでUNIXですけどwwww
>>244
とりあえず eval でいけそうですね。
FILES="{tex,org,.emacs.d,.w3m}"
rsync -avzu -e ssh `eval echo ${FILES}` hoge.example.net:
rsync -avzu -e ssh `eval echo hoge.example.net:${FILES}` .
こういう感じでしょうか
ありがとうございました。
0249名無しさん@お腹いっぱい。
2010/05/06(木) 13:39:14> rsync -avzu -e ssh `eval echo hoge.example.net:${FILES}` .
こっちはeval不要。
0250240
2010/05/06(木) 13:50:49% ls -l /bin/{sh,bash}
-rwxr-xr-x 1 root wheel 1346544 2010-02-05 09:41 /bin/bash*
-r-xr-xr-x 1 root wheel 1346624 2010-02-05 09:43 /bin/sh*
% diff /bin/{sh,bash}
Binary files /bin/sh and /bin/bash differ
微妙に違うみたいですがほとんど同じなのかも知れません。
eval 不要でしょうか?
evalがないと、
ls -d `echo hoge.example.net:${FILES}`
ls: cannot access hoge.example.net:{tex,org,.emacs.d,.w3m}: No such file or directory
となって{}を展開してくれませんでした。
0251名無しさん@お腹いっぱい。
2010/05/06(木) 14:00:100252名無しさん@お腹いっぱい。
2010/05/06(木) 14:01:45rsync -avzu -e ssh hoge.example.net:${FILES} .
ところで、FILESじゃなくてDIRSだろ。
0253名無しさん@お腹いっぱい。
2010/05/06(木) 14:04:080254名無しさん@お腹いっぱい。
2010/05/06(木) 14:27:32なぜ?
0255名無しさん@お腹いっぱい。
2010/05/06(木) 22:19:46$ echo $SHELL
/bin/bash
$ bash --version
GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.
0256名無しさん@お腹いっぱい。
2010/05/07(金) 12:22:190257名無しさん@お腹いっぱい。
2010/05/07(金) 21:52:57お前バカだろ
0258名無しさん@お腹いっぱい。
2010/05/07(金) 22:02:52$ /bin/sh --version
GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin10.0)
Copyright (C) 2007 Free Software Foundation, Inc.
$ ls -il /bin/sh /bin/bash
12727992 -rwxr-xr-x 1 root wheel 1346544 2010-02-05 09:41 /bin/bash*
12728038 -r-xr-xr-x 1 root wheel 1346624 2010-02-05 09:43 /bin/sh*
てっきりハードリンクだろうと思ったらちがったので驚いている。
0259名無しさん@お腹いっぱい。
2010/05/07(金) 22:03:23Mac OS Xの /bin/shは Bash七日? と聞いてるんだから、
$ /bin/sh --version の結果を貼らないと。
0260名無しさん@お腹いっぱい。
2010/05/08(土) 00:10:320261名無しさん@お腹いっぱい。
2010/05/09(日) 04:44:03Ex.
Pos: 0.3s 10f ( 0%) 4.88fps Trem: 15min 14mb A-V:0.023 [0:0]
こういったコマンドの表示を必要な部分だけ切り出して表示したり、
プログレスバーを作ったりしたいのですが可能でしょうか?
Bashでエスケープシーケンスを使うんだろうなぁって思うのですが、とっ
かかりが分からなくて。
ご存じであれば、ご教授お願いします。
0262名無しさん@お腹いっぱい。
2010/05/09(日) 10:17:470263名無しさん@お腹いっぱい。
2010/05/09(日) 10:36:480264名無しさん@お腹いっぱい。
2010/05/09(日) 11:07:02bash仮定していいのかな、この場合。
* IFSとset
* ${var#pattern} # のほかに ## % %% など。
* sedのような外部コマンド
0265名無しさん@お腹いっぱい。
2010/05/09(日) 11:15:18mencoderだということをわかって回答してる?
mencoderが出してくるメッセージは改行なしで1行を書き換えたりしてるので、
行単位に処理する方法では対応できないし、画面に見える文字のまま取り出せる
わけではないんだよ。
0266名無しさん@お腹いっぱい。
2010/05/09(日) 11:24:15( i )))
/ ̄\ / /
| ^o^ | ノ / < いみがわかりませんなぁ
\ / ,/
/ _ /´
(___)/
0267名無しさん@お腹いっぱい。
2010/05/09(日) 11:36:33でも、mencoder改造した方が楽だよね。
0268名無しさん@お腹いっぱい。
2010/05/09(日) 11:45:22いや、少なくとも ESC [ J とかのシーケンスは含まれてる。
0269名無しさん@お腹いっぱい。
2010/05/09(日) 11:49:430270名無しさん@お腹いっぱい。
2010/05/10(月) 16:00:31バッククォートによるコマンド置換の説明で以下のコマンドが出てきました。
STRING=`echo "abc \`echo def\` ghi"`
echo $STRING
期待値は abc def ghi ですが、
\`echo def\` 部分が `echo def` という文字列にならずコマンドとして
認識されるい理由がわかりません。
かといってバックスラッシュ取っちゃうと動かないわけで。
0271名無しさん@お腹いっぱい。
2010/05/10(月) 16:16:21外側の ` ` で囲まれている時点で、
たとえ " " で囲んでも、" " の中のバッククォートの意味は消えない。
よって、` ` のネスティングとみなされてコマンド置換される。
バックスラッシュを取ると動かなくなるのは、
そうすると最初の `echo "abc ` まででクォートとみなされて
解釈が期待通りにならないから。
0272名無しさん@お腹いっぱい。
2010/05/10(月) 16:22:33バックスラッシュの部分は、シェルと、外側のechoコマンドとによって
2回解釈されるので、解釈の結果コマンド置換が実行される。
0273名無しさん@お腹いっぱい。
2010/05/10(月) 16:28:16大外の `` がポイントということですか。納得です。
バックスラッシュ取ると動かなくなる理由は、そいういう
ことなんだろうなと思ってました。
即レスTHXです。
0274名無しさん@お腹いっぱい。
2010/05/10(月) 16:56:170275名無しさん@お腹いっぱい。
2010/05/10(月) 16:58:040276名無しさん@お腹いっぱい。
2010/05/10(月) 17:11:09まだ最初の数十ページしか読んでないけど、丁寧に説明してくれてて
読みやすい。tips的な解説もあるし。
どういうところが古臭いと感じるん?
>>274
( ) の説明はまだ数ページ先だ!笑
0277名無しさん@お腹いっぱい。
2010/05/14(金) 13:41:09echo hoge > /dev/tcp/192.168.0.10/5000
を実行したのですが、接続されません。
/dev/tcp/192.168.0.10/5000: No such file or directory
になってしまいます。なぜでしょうか。
192.168.0.10:5000にはサーバプログラムが存在してて
telnet等で接続可能な状態です。
0278名無しさん@お腹いっぱい。
2010/05/14(金) 13:45:410279名無しさん@お腹いっぱい。
2010/05/14(金) 14:01:13Linux板に行ってきます。
0280名無しさん@お腹いっぱい。
2010/05/14(金) 14:02:41エスパーすると、bashを使ってるつもりでbashではないのでは?
接続されない場合は、connect: Connection refused と表示され、
No such file or directory とはならない。
bash以外のシェルだと、No such file or directoryになるので。
0281名無しさん@お腹いっぱい。
2010/05/14(金) 14:07:11間違えて csh(笑) で実行するとそのメッセージになるな。
0282名無しさん@お腹いっぱい。
2010/05/14(金) 14:31:110283名無しさん@お腹いっぱい。
2010/05/14(金) 14:45:010284名無しさん@お腹いっぱい。
2010/05/14(金) 14:48:160285名無しさん@お腹いっぱい。
2010/05/14(金) 14:54:180286名無しさん@お腹いっぱい。
2010/05/14(金) 14:56:05linuxじゃなくても bashなら /dev/tcp は使えるよ。デバイスファイルじゃないし。
>>285
おまえあほ。
/dev/tcpなんてデバイスファイルはない。
これは Bashの機能。
FreeBSDでも bashを使えば /dev/tcp は使える。
0287名無しさん@お腹いっぱい。
2010/05/14(金) 15:11:540288名無しさん@お腹いっぱい。
2010/05/14(金) 15:15:28言い訳見苦しいね。Linuxを目のカタキにしてると /dev/tcpが Linux独自のデバイスに
見えたんだろうね。*BSDでもSolarisでも bashで /dev/tcpは使えるんだよwww
0289名無しさん@お腹いっぱい。
2010/05/14(金) 15:30:24必死だな。バカ。
そのように見えたというソース出せよ。ww
0290名無しさん@お腹いっぱい。
2010/05/14(金) 15:42:30>>285
0291名無しさん@お腹いっぱい。
2010/05/14(金) 15:59:19ソケットを開くという特別解釈をbashの中でしてるんだ。 キモイ。
0292名無しさん@お腹いっぱい。
2010/05/14(金) 16:01:29> 言い訳見苦しいね。Linuxを目のカタキにしてると /dev/tcpが Linux独自のデバイスに
> 見えたんだろうね。*BSDでもSolarisでも bashで /dev/tcpは使えるんだよwww
こういうバカな思いつきをするんだろうな。
お前、昨日FreeBSDスレに居たJava厨だろ。バカさ加減が同レベルだ。ww
0293名無しさん@お腹いっぱい。
2010/05/14(金) 16:09:27>バカ? /dev/tcpだから犬板行けって言ったんだよ。
>バカ? /dev/tcpだから犬板行けって言ったんだよ。
>バカ? /dev/tcpだから犬板行けって言ったんだよ。
とても恥ずかしいことなので3回言いましたwww
0294名無しさん@お腹いっぱい。
2010/05/14(金) 16:14:34$ bash --version
GNU bash, version 3.2.17(1)-release (i386-apple-darwin9.0)
Copyright (C) 2005 Free Software Foundation, Inc.
$ exec 3<>/dev/tcp/www.google.com/80
$ echo -e "GET / HTTP/1.1¥n¥n">&3
$ cat <&3
HTTP/1.1 200 OK
Date: Fri, 14 May 2010 07:12:54 GMT
...
0296名無しさん@お腹いっぱい。
2010/05/14(金) 16:25:14/dev/tcp じゃなくて /inet/tcp だけど。
0297名無しさん@お腹いっぱい。
2010/05/14(金) 19:17:20お前本当に頭が弱いな。
> *BSDでもSolarisでも bashで /dev/tcpは使えるんだよwww
> *BSDでもSolarisでも bashで /dev/tcpは使えるんだよwww
> *BSDでもSolarisでも bashで /dev/tcpは使えるんだよwww
> *BSDでもSolarisでも bashで /dev/tcpは使えるんだよwww
> *BSDでもSolarisでも bashで /dev/tcpは使えるんだよwww
使えてりゃ質問しねーんだよ。www
0298名無しさん@お腹いっぱい。
2010/05/14(金) 19:22:04お前本当に頭が弱いな。
bashで /dev/tcpが使えるはずなのに使えなかったから質問してたんだろ。
(もともと使えないものならそもそもそういう使い方をしないから質問もしない)
(オチは、./configure 時に --disable してただけ)
ところが、>>285 は、/dev/tcpというデバイスファイルがLinuxにはあって、
Linuxでしか /dev/tcpが使えないものと勘違いしたんだよ、、、
0299名無しさん@お腹いっぱい。
2010/05/14(金) 20:20:13お前かわいそうなくらい頭が弱いな。
> ところが、>>285 は、/dev/tcpというデバイスファイルがLinuxにはあって、
> Linuxでしか /dev/tcpが使えないものと勘違いしたんだよ、、、
それはお前の妄想。
*BSD(のports, pkgsrc)、Solaris(のコンパイル済みの奴)は使えるように
コンパイルしてある。従って使えないのは>>283の指摘通りそのようにコ
ンパイルしているから。
従って、>>285
> *BSDでもSolarisでも bashで /dev/tcpは使えるんだよwww
> *BSDでもSolarisでも bashで /dev/tcpは使えるんだよwww
> *BSDでもSolarisでも bashで /dev/tcpは使えるんだよwww
> *BSDでもSolarisでも bashで /dev/tcpは使えるんだよwww
> *BSDでもSolarisでも bashで /dev/tcpは使えるんだよwww
使えてりゃ質問しねーんだよ。www
■ このスレッドは過去ログ倉庫に格納されています