シェルスクリプト総合 その7
レス数が900を超えています。1000を超えると表示できなくなるよ。
0001ミスターシェル
2006/09/07(木) 13:00:11スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>1-6くらい)をご覧ください。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
Linuxユーザは/bin/shの正体がbashなので特に注意。
・csh/tcshのシェルスクリプトは推奨されません。
(理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
manや参考リンクを見ましょう。
aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
0824名無しさん@お腹いっぱい。
2007/02/03(土) 20:13:370825名無しさん@お腹いっぱい。
2007/02/03(土) 20:17:100826820
2007/02/03(土) 20:19:07あ・・・、マジでごめソ・・・orz
cat text.txt
が正解。
というか初心者がパイプを覚えるには最も分かりやすい例だと思うけどね。
cat hoge.txt | sort
0827名無しさん@お腹いっぱい。
2007/02/03(土) 20:23:030828名無しさん@お腹いっぱい。
2007/02/03(土) 20:25:490829名無しさん@お腹いっぱい。
2007/02/03(土) 20:27:31べつにそういう使いかた教えたせいじゃないだろう
0830820
2007/02/03(土) 21:14:27「全国の都道府県庁所在地の中で
2007年1月に冬日が多かった順に並び替えます」
その結果です。
http://sheel.mydns.jp/~sheel/fuyubikencho0701.txt
スクリプトはこちらです。
http://sheel.mydns.jp/~sheel/fuyubikencho0701.sh
「全国の都道府県庁所在地の中で
2006年8月に猛暑日が多かった順に並び替えます」
その結果です。
http://sheel.mydns.jp/~sheel/moushobikencho0608.txt
スクリプトはこちらです。
http://sheel.mydns.jp/~sheel/moushobikencho0608.sh
これを見ると、
佐賀、熊本、京都、名古屋は
夏場は日本一暑い割に冬場も不相応に寒いことがわかりますね。
0831名無しさん@お腹いっぱい。
2007/02/04(日) 01:24:10変数$hogeaと変数$hogebを連結しようと思います。
$hogeaの中身は
1
3
5
4
8
7
3
$hogebの中身は
1023
1032
1001
1002
1003
1009
1018
これをこんなふうにしたいのですが、
1 1023
3 1032
5 1001
4 1002
8 1003
7 1009
3 1018
ちょっと勉強して感じではよくわかりませんでした。
もうちょっと勉強してみます。
0832名無しさん@お腹いっぱい。
2007/02/04(日) 03:20:350833831
2007/02/04(日) 04:33:44できました!!!
変数が20個くらいあったのですが、
echo "$hogehoge1" | paste file1.txt - >file2.txt
echo "$hogehoge2" | paste file2.txt - >file3.txt
・・・・・
echo "$hogehoge20" | paste file20.txt - >out.txt
とやることでなんとかなりました。
これが47x12x47=26,508回繰り返さないと行けない処理で、
ハードディスクは痛めつけるますがこれ一回だけやればいいので
これでがまんすることにします。
もっとメモリ内のみで済む方法ってないんでしょうね・・・。
0834名無しさん@お腹いっぱい。
2007/02/04(日) 07:57:230835名無しさん@お腹いっぱい。
2007/02/04(日) 07:58:300836名無しさん@お腹いっぱい。
2007/02/04(日) 16:11:520837831
2007/02/04(日) 19:45:16例えばどういう方法がありますか?
わたしがやりたいのは、
気象庁のWebサイトから各都道府県庁所在地の
1961年以降の毎日のデータを2007年1月まで
一気に取得し、
例えば2007年1月の熊本(47814)のデータを
あとでとりだしやすいように加工した後に
「20070147814」
というファイル名で保存していく、ということです。
今朝から一括ダウンロードを始めましたがまだまだ終わりそうにありません。
24時間くらいかかりそうです・・・orz
こういう一回だけやれば済む使い捨てスクリプトをかくのに
シェルスクリプト以外になにかいい方法がありますか?
0838831
2007/02/04(日) 19:59:03シェルスクリプトはこんな感じ。
ttp://sheel.mydns.jp/~sheel/alldataget.sh.txt
使い捨てだね。
そのダウンロードの結果が例えばこれ。
ttp://sheel.mydns.jp/~sheel/19920147819.txt
2年ほど前もこのスレで言われてたんだけど、
毎回毎回気象庁にデータを取りに行くより
一回だけ一括ダウンロードしておいて
ローカルで参照した方がスクリプト自体も高速化する、ってことと
自分自身が一括ダウンロードをするだけのスキルが可能になったので
ついに念願の一括ダウンロードをやっています。
試しにダウンロードが終わった部分だけで
ある連続した5年間の1月の47都市の冬日の日数の平均値を計算し
その平均値の大きい順に並べ替えてみました。
こういうのをダウンロードでやろうとすると小一時間以上?かかるのだけど
ローカルに保存しておくと1〜2分くらいで終わりますね。
0839名無しさん@お腹いっぱい。
2007/02/04(日) 20:17:39PerlやRubyは考慮しないのかな、ということではないかと。
シェルスクリプトにはパズル的なおもしろさはあるけど、
若干の無理矢理感はあるし、外部コマンド使いまくりでモタモタするし。
0840831
2007/02/04(日) 20:36:39なるほど。
モタモタして時間がかかるのは確かだしね。
つか、俺的にはPerlもRubyもシェルスクリプトの1コマンド、という認識。
Rubyはよく知らんけど
Perlはシェルスクリプトと比べて意味がわかりづらいので
なかなか重い腰が上がらないんだよね。
あと、こういうデータを元にして動的なWebコンテンツをつくるには
やっぱphpでつか?
0841名無しさん@お腹いっぱい。
2007/02/04(日) 20:52:56なんでもええよ。
シェルスクリプトでもいいし。
ある程度アクセス数が多くなるなら、シェルスクリプトではきついけどね。
0842名無しさん@お腹いっぱい。
2007/02/04(日) 23:39:23そんなあなたにはRubyお薦め。
Perl挫折した俺が言うんだからまちがいない。
0843名無しさん@お腹いっぱい。
2007/02/05(月) 00:30:47その一方でウェブサービスをC++で書いたCGIで実現している奴もいる。
言語自体の得意分野や不得意分野があるのはその通りかも知れんが、
慣れた言語で適当にやるのも重要であるのだと思うぜ。所詮スクリプト。
そんな俺はPHPをおすすめしておこうかな
0844名無しさん@お腹いっぱい。
2007/02/05(月) 00:40:440845名無しさん@お腹いっぱい。
2007/02/05(月) 01:23:19動的なWebコンテンツというなら、テキスト処理に長けていることが条件かな。
PHPでもPerlでもRubyでも、あるいは他のものでもいいと思う。
慣れているものを選べばいいのでは。
どれも初めてトライというなら、適当に情報を拾って見比べてみて、
自分に合いそうだと思ったものにすればいんじゃね?
シェルスクリプトは、テキスト処理能力に関しては
長けた言語と比べるとかなり見劣りする。
ちょっと凝ったものになると素のシェルスクリプトではとても苦しい。
>>837ぐらいの処理なら、シェルスクリプト(+awkやsed)でもどうにかなるだろうけど。
0846名無しさん@お腹いっぱい。
2007/02/05(月) 16:28:420847名無しさん@お腹いっぱい。
2007/02/05(月) 16:37:56sort < hoge.txt
で済むから。
0848831
2007/02/05(月) 16:59:15そうですか。ありがとう。
>>843
phpも挑戦したことはあるけど
なんかやっぱPerlほどではないけど小難しい感じがしました・・。
>>842
Rubyですか。
使ったことないけど今確認したら
ちゃんとMacOSXにもプリインストールされてるみたいなので、
Perlに挫折した俺としてもRubyに挑戦してみようかな。
日本人が作ったみたいだしね。
0849名無しさん@お腹いっぱい。
2007/02/05(月) 17:08:42非常に解りやすい説明をありがとう。
0850名無しさん@お腹いっぱい。
2007/02/06(火) 22:48:39sort hoge.txt
の方が1文字少ない
0851名無しさん@お腹いっぱい。
2007/02/06(火) 22:53:30sort hoge.txt だと、もしhoge.txtが存在しないか、またはpermission deniedの場合
にも、一旦sortコマンドが起動された後でエラーになるため、ちょっと無駄になる。
sort < hoge.txtだと、hoge.txtが読めない場合はシェルのレベルでエラーになり、
sortコマンド自体起動されないので無駄がない。
0852名無しさん@お腹いっぱい。
2007/02/06(火) 23:27:58trみたいなファイルを引数に取らないのもあるわけで。
cat hoge.txt | tr a-z A-Z → tr a-z A-Z < hoge.txt
0853名無しさん@お腹いっぱい。
2007/02/06(火) 23:30:260854名無しさん@お腹いっぱい。
2007/02/06(火) 23:46:29確かに、こっちの方がcat以外でも同じ書き方になるから、ぱっと見わかりやすいか。
0855名無しさん@お腹いっぱい。
2007/02/06(火) 23:56:45< hoge.txt tr a-z A-Z
0856名無しさん@お腹いっぱい。
2007/02/07(水) 00:08:15知らなかった
0857名無しさん@お腹いっぱい。
2007/02/07(水) 00:36:54なんてのも可だったり。
0858831
2007/02/07(水) 03:53:44理由
・初心者がパイプの意味を理解するのに適している
・ < を使う方法と大差ない
・後ろから < で入力とか気持ち悪い
0859名無しさん@お腹いっぱい。
2007/02/07(水) 04:18:00理由の一つ目は、リダイレクトなら
「初心者がリダイレクトの意味を理解するのに適している」
と言い換えられるな。
理由の二つ目は、全然「catの方がいい」理由にはなってないな。
あんたにとって「大差ない」かもしれないが、少なくとも
タイプ量が多いし、無駄なプロセスも増える。
理由の三つ目は、もはや意味不明だな。何だそりゃ。
シェルのシンタクスが非常に美的であるとは俺も言わないが、
リダイレクトはシェルの基本だろ。
0860名無しさん@お腹いっぱい。
2007/02/07(水) 09:15:440861名無しさん@お腹いっぱい。
2007/02/07(水) 09:44:290862名無しさん@お腹いっぱい。
2007/02/07(水) 11:15:52アンカ間違ってるぞ。 正しくは >>859 だろう。
0863名無しさん@お腹いっぱい。
2007/02/07(水) 11:22:45自演乙。
ダメ人間は >>858
0864名無しさん@お腹いっぱい。
2007/02/07(水) 11:22:46sort<hoge.txt
で文字数いっしょだ。
0865名無しさん@お腹いっぱい。
2007/02/07(水) 11:29:170866名無しさん@お腹いっぱい。
2007/02/07(水) 11:38:540867名無しさん@お腹いっぱい。
2007/02/07(水) 11:39:580868名無しさん@お腹いっぱい。
2007/02/07(水) 12:56:56cat hoge して中身を見て,その結果を | で別のコマンドに流し込んで...
という部分を省略できるようになると冗長と感じるわけで
オレはコマンドライン編集を使いながら書いていく方が多いから
いまだに cat hoge | から始まるよ
% cat hoge
...出力...
% cat hoge | awk -F: '{print $1, $8}'
...出力...
% ...
そりゃ後から見ながら最適化すれば < hoge とか
コマンドの引数に hoge 指定とかになるんだが
0869名無しさん@お腹いっぱい。
2007/02/07(水) 12:59:13初心者ですが、catの左側にある % というのは何のコマンドですか?
うちでは % を付けるとエラーになるのですが・・
0870名無しさん@お腹いっぱい。
2007/02/07(水) 13:08:30英語のテキストならless、日本語ならlv、構文のあるテキストファイルならvim、バイナリならbvi。
よってcatは本当に結合したい時にしか使わんが、人それぞれか。
0871名無しさん@お腹いっぱい。
2007/02/07(水) 13:09:09Bourneシェルのデフォルトが$、Cシェル系は%なので両方が見られる。
0872名無しさん@お腹いっぱい。
2007/02/07(水) 13:13:100873名無しさん@お腹いっぱい。
2007/02/07(水) 13:13:55ゴマエー
0874名無しさん@お腹いっぱい。
2007/02/07(水) 13:22:21という命題はは排他ではない。
0875名無しさん@お腹いっぱい。
2007/02/07(水) 13:27:510876831
2007/02/07(水) 15:31:42そうそう、まさにそのとおり。
俺もそんなやり方でやっている。
viとかpicoとかでは>>868のような処理はできんだろ。
意味分かる?w
0877名無しさん@お腹いっぱい。
2007/02/07(水) 15:55:26...出力...
$ < hoge cat ← ここで Ctrl-Wを押す
$ < hoge ← catが消える
$ < hoge awk -F: '{print $1, $8}'
...出力...
↑こうすれば無問題。無駄なcatやパイプは要らない。
0878名無しさん@お腹いっぱい。
2007/02/07(水) 15:57:20なんでそんなにこだわるのかわからん。
0879名無しさん@お腹いっぱい。
2007/02/07(水) 15:58:360880名無しさん@お腹いっぱい。
2007/02/07(水) 16:33:11$ cat hoge
しまった長い... ^C
$ head hoge
考える...
$ tail hoge
考える...
$ sed -e '..' hoge |head
更に考える...
$ sed -e '..' -e '..' hoge |head
更に考える...
$ sed -e '..' -e '..' -e '..' hoge |head
やっぱ、catを使いたがるのは、ダメ人間だな。
0881名無しさん@お腹いっぱい。
2007/02/07(水) 16:42:250882名無しさん@お腹いっぱい。
2007/02/07(水) 16:56:480883名無しさん@お腹いっぱい。
2007/02/07(水) 18:05:59sed -n か awk を使えばできると思うのですが難しいです。
<span>
数行
</span>
数行
<span>
数行
</span>
0884名無しさん@お腹いっぱい。
2007/02/07(水) 18:19:17>>743
0885831
2007/02/07(水) 18:50:30今日、仕事をサボって(w)
本屋に行ってきて物色してみました。
Rubyがよさげだったので
さっそく「たのしいRuby」という本を
買ってきました。
ttp://sheel.mydns.jp/~sheel/ruby.jpg
ワクワクしますよ。
0886名無しさん@お腹いっぱい。
2007/02/07(水) 20:54:51xmlstarlet とかのツールを補助に使えばいいと思うよ。
XSLT でも Xpath でも好きにコマンドラインから使える。
0887名無しさん@お腹いっぱい。
2007/02/07(水) 22:52:08<span> と </span> のが完全に1行ずつなら簡単だね
0888名無しさん@お腹いっぱい。
2007/02/07(水) 22:55:59そのように整形する前処理をするとかね
0889831
2007/02/08(木) 09:49:41おれなら
cat -nとかでhtml書類を出力し
それをパイプしてgrepなどで一番最初に遭遇する
<span>と</span>をみつけ、
cut -d¥: -f1を使ってその行頭の数値(=行番号)をよみとり、
その結果をまた
それをパイプしてgrepなどで一番最初に遭遇する
<span>と</span>をみつけ、
cut -d¥: -f1を使ってその行頭の数値(=行番号)をよみとり、
という繰り返しでやるかな。
0890831
2007/02/08(木) 10:05:40>>883
おれなら
cat -nとかでhtml書類を出力し
それをパイプしてgrepなどで一番最初に遭遇する
<span>と</span>をみつけ、
cut -d¥: -f1を使ってその行頭の数値(=行番号)をよみとり、
cat -nする前のhtmlに対してその数値の間をsedのdオプションで削除し、
その結果をまた
cat -nとかで出力し、
それをパイプしてgrepなどで一番最初に遭遇する
<span>と</span>をみつけ、
cut -d¥: -f1を使ってその行頭の数値(=行番号)をよみとり、
cat -nする前のhtmlに対してその数値の間をsedのdオプションで削除し、
という繰り返しでやるかな。
0891名無しさん@お腹いっぱい。
2007/02/08(木) 10:37:59なんてケースは考えるだけ無駄だったりするよな。
0892名無しさん@お腹いっぱい。
2007/02/08(木) 11:26:21RSSとか扱ってると、結構あるけど
0893名無しさん@お腹いっぱい。
2007/02/08(木) 11:30:47たいていこういう質問投げるやつって投げっぱなしだよね。
0894名無しさん@お腹いっぱい。
2007/02/08(木) 12:14:030895883
2007/02/08(木) 14:59:160896名無しさん@お腹いっぱい。
2007/02/08(木) 16:26:18知っているかた教えてください。
if [ -e /work/IBMIHS/logs/access_log ];
then
mv /work/IBMIHS/logs/access_log /logs/auditlog/access_log.$(date "+%Y%m%d") >> ${LOG_FILE}
echo "IHSログローテーション(アクセスログ)は成功しました。"
else
echo "IHSログローテーションは失敗しました。"
exit 1
fi
if [ -e /work/IBMIHS/logs/error_log ];
then
mv /work/IBMIHS/logs/error_log /logs/auditlog/error_log.$(date "+%Y%m%d") >> ${LOG_FILE}
echo "IHSログローテーション(エラーログ)は成功しました。"
else
echo "IHSログローテーションは失敗しました。"
exit 1
fi
0897名無しさん@お腹いっぱい。
2007/02/08(木) 16:45:32↑じゃダメな理由あるの?
0898名無しさん@お腹いっぱい。
2007/02/08(木) 17:12:50if [ -e /work/IBMIHS/logs/$log ];
then
else
fi
done
0899名無しさん@お腹いっぱい。
2007/02/08(木) 17:13:19for f in access_log error_log; do ....
ってことをしたいのか?
0900名無しさん@お腹いっぱい。
2007/02/08(木) 17:17:12ま、それはおいといて、単純に繰り返し部分をまとめるだけなら、
SRCDIR="/work/IBMIHS/logs"
DESTDIR="/logs/auditlog"
for FN in "access_log error_log"
do
if [ -e "${SRCDIR}/${FN}" ]
then
mv "${SRCDIR}/${FN}" "${DESTDIR}/${FN}.$(date "+%Y%m%d")" >> ${LOG_FILE}
echo "IHSログローテーション(${FN})は成功しました。"
else
echo "IHSログローテーションは失敗しました。"
exit 1
fi
done
とか。
0901名無しさん@お腹いっぱい。
2007/02/08(木) 17:32:12for FN in "access_log" "error_log"
0902名無しさん@お腹いっぱい。
2007/02/08(木) 19:58:24sudo -u hoge echo "hoge" > test.txt
とすると
test.txt の所有権は hoge ではなく、
sudo の実行者になります。
test.txt を hogeの所有権のファイルとして作成したいのですが、
どこに間違いがあるかご教授お願いします。
0903名無しさん@お腹いっぱい。
2007/02/08(木) 20:05:21sudo -u hoge sh -c 'echo "hoge" > test.txt'
0904名無しさん@お腹いっぱい。
2007/02/08(木) 20:07:161. > test.txt
2. sudo -u hoge echo "hoge"
の順で処理されるからね。
sudo -u hoge sh -c 'echo "hoge" > test.txt'
0905902
2007/02/08(木) 20:09:21レスありがとうございます、
上の内容をためしたところ、存在しない、といったエラーが出てしまいました。
お助けを〜〜
sh: test.txt: No such file or directory
0906902
2007/02/09(金) 01:44:34再度試してみたらいけました。
ありがとうございました。
教えていただいた内容も納得です!
ちょっと関連した内容になるのですが、
"hoge"の部分に改行などを含んだ変数を入れたいのですが、
うまくいきません。
どうやら改行ごとに、シェルが実行されてしまっている?ようです。
複数行にわたった変数を使用したい場合、
どのように記述すればよいでしょうか?
何度もすいません orz
0907名無しさん@お腹いっぱい。
2007/02/09(金) 06:43:270908名無しさん@お腹いっぱい。
2007/02/09(金) 10:17:57継続行を入力させてくれるかも。
0909名無しさん@お腹いっぱい。
2007/02/09(金) 11:38:06何もする必要ない。"hoge" の途中に改行があっても改行はそのまま保存される。
もし、そうならないなら、sudoを実行しているコマンドラインのシェルが、
普通のB-sh系のシェルじゃないんだろう。
(あるいは、sudo先のユーザーのログインシェルが B-sh系じゃないとか)
sh bash zsh ksh 等の B-sh系を使うこと。
0910902
2007/02/09(金) 15:59:08レスありがとうございます。
ある変数の内容をファイルに書き込みたい、
という場合、echo とリダイレクトを使う以外にありますでしょうか?
0911名無しさん@お腹いっぱい。
2007/02/09(金) 16:04:07echo "$変数" | sudo -u hoge sh -c 'cat > test.txt'
sudo先のshでechoすると、クォートが2重になってややこしいから、
sudo前にechoしておいてパイプでつなぐ。
0912902
2007/02/09(金) 16:30:53orz ありがとうございます、うまくいきました。
クオートが入れ子になってて鬱入ってました。
発想の転換ですね、さすがみなさん視点がすごいです!!
本当にありがとうございました!!!
0913名無しさん@お腹いっぱい。
2007/02/11(日) 17:22:09「ls -l」形式のファイル一覧が入っているテキストファイル(引数)
を1行ずつ読み込み、ファイル名に「.bak」が含まれるファイルを
消去するシェルスクリプトを作成したいのですが、頭の「#!/bin/sh」
を書いた時点で力尽きました。
「while read」を使う、というところまでは理解出来たのですが、
文法等がさっぱりで…どなたかご教授願えないでしょうか?
0914名無しさん@お腹いっぱい。
2007/02/11(日) 17:33:05read 使うと逆に難しそう。
grep .bak したのを sed か awk かなんかで加工して rm、がいいと思う。
> 「ls -l」形式のファイル一覧が入っているテキストファイル(引数)
この前提は変えられない?
ls -l 形式は扱いづらそうだから
find とか使った方がいいと思うんだが。
0915名無しさん@お腹いっぱい。
2007/02/11(日) 17:37:27超簡単。1行で書ける。
while read line; do case $line in *.bak);; *) echo "$line";; esac; done < file
>>914
おまえには難しかったようだね。
0916名無しさん@お腹いっぱい。
2007/02/11(日) 17:48:12それって >>913 の要求満たしてるの?
0917名無しさん@お腹いっぱい。
2007/02/11(日) 17:50:39「ls -l出力が書かれたファイルの中から、ファイル名 *.bakのファイルを消去する」 のか?
0918名無しさん@お腹いっぱい。
2007/02/11(日) 17:53:13わかりにくい質問でどうも済みませんでした。
前者の意味です。>>915 でできました。Thanksです。
0919名無しさん@お腹いっぱい。
2007/02/11(日) 17:54:48なら grep -v '\.bak$' でいいじゃん。
シンボリックリンクに対応してないけど。
0920913
2007/02/11(日) 18:02:01申し訳ありません。説明不足でした。
「ls -l出力が書かれたファイルの中から、ファイル名 *.bakのファイルを消去する」
が目的です。
ファイルリストをgrepして*.bakを含む行だけ取り出した後、awkを使用してls -lの
リストからファイル名を抜き出して…とか色々と考えていたのですが、それらを
シェルスクリプトで作成するだけの知識とか度胸とかが足りなくて困っております。
>915
回答ありがとうございます。「esacって何?」とか調べていたら返事が遅れて
しまいました。
0921名無しさん@お腹いっぱい。
2007/02/11(日) 18:03:460922名無しさん@お腹いっぱい。
2007/02/11(日) 18:04:520923名無しさん@お腹いっぱい。
2007/02/11(日) 18:06:10だったら、↓で行ける。(ls -l であって、ls -lR ではないんだから)
while read perm link usr grp size mon day year file other
do
case $file in
*.bak) rm "$file";;
esac
done < ls-l-file.txt
レス数が900を超えています。1000を超えると表示できなくなるよ。