トップページunix
985コメント289KB

シェルスクリプト総合 その8

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2007/02/15(木) 14:28:44
シェルスクリプトの総合スレです。
スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>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 でトレースしましょう。

前スレ
シェルスクリプト総合 その7
http://pc10.2ch.net/test/read.cgi/unix/1157601611/
0490ウサチャソ2007/05/22(火) 22:14:31
CTRL+Vが楽だったんで、つい…

ちなみに、>>489 でも >>486 でもCygwinだと同じ表示。

-rw-r--r-- 1 ウサチャソ なし 0 May 22 22:10 aaaa?aaaa

今日始めて知った。
0491ウサチャソ2007/05/22(火) 22:15:58
あ゛っごめん、Cygwinは「--show-control-chars」が必要だった…。
スレ違いなんでもう消えます、スマソ
0492名無しさん@お腹いっぱい。2007/05/24(木) 20:33:53
質問します。

lsnrctl >>_EOF_
set log_file listener.tmp
RET=$?
if [ $RET -ne 0 ];then
logger -t loglog -p local1.notice "切り替えに失敗しました"
exit 1
fi
exit
_EOF_

という事をしたいのですがどうしてもsetコマンド以降エラーに
なってしまいます。
対処法を教えていただけないでしょうか?
0493名無しさん@お腹いっぱい。2007/05/24(木) 20:51:21
逆だ。
lsnrctl <<_EOF_
0494名無しさん@お腹いっぱい。2007/05/24(木) 20:55:16
あと、ヒアドキュメントの部分は、LSNRCTLのコマンドしか受け付けないぞ。
0495名無しさん@お腹いっぱい。2007/05/24(木) 21:23:10
すいません逆に書いてました。
やはりLSNRCTLコマンドしか受け付けないですか・・・
う〜ん、どうしてもLSNCTLの中でシェルスクリプトの処理の記述を
したかったのですが無理そうですね。
ありがとうございました。
0496名無しさん@お腹いっぱい。2007/05/28(月) 07:13:03
質問。
ファイルの最終から20行を削除したい。
どうしたらいいでしょうか?
0497名無しさん@お腹いっぱい。2007/05/28(月) 07:46:41
>>496
wc で数えて、head で切り出すぐらいしか考え付かない
0498名無しさん@お腹いっぱい。2007/05/28(月) 08:09:27
awk
0499名無しさん@お腹いっぱい。2007/05/28(月) 08:33:29
tac なんてLinuxでもないかぎり標準装備じゃない罠

cat file | tac | sed '1,20d' | tac
0500名無しさん@お腹いっぱい。2007/05/28(月) 12:43:49
無意味なcat出た
0501名無しさん@お腹いっぱい。2007/05/28(月) 14:05:40
tacが使えなければ sed '1!G;h;$!d' すればいいじゃない。
0502名無しさん@お腹いっぱい。2007/05/28(月) 15:55:05
cat!出た!cat出た!得意技!cat出た!cat!これ!cat出たよ〜〜!
0503名無しさん@お腹いっぱい。2007/05/28(月) 16:13:35
>>502
楽しそうだな
0504名無しさん@お腹いっぱい。2007/05/28(月) 18:27:43
俺は限界だと思った
0505名無しさん@お腹いっぱい。2007/05/29(火) 00:14:45
tail つかって最後から20行みれ
で、>>499しる
0506名無しさん@お腹いっぱい。2007/05/29(火) 00:58:13
基本的にサブシェルはshを新たに起動するよりは動作が軽いですよね?
0507名無しさん@お腹いっぱい。2007/05/29(火) 01:26:05
>>498
awkには入力ファイルの行数を保持する組み込み変数はないんじゃね?
だから、結局wcでカウントしないとダメだったり。
0508名無しさん@お腹いっぱい。2007/05/29(火) 01:47:08
は?

awk '{a[NR]=$0}NR>20{print a[NR-20]}'
0509名無しさん@お腹いっぱい。2007/05/29(火) 02:37:14
>>508 短くていいが、でかいファイル通すとメモリが…
0510名無しさん@お腹いっぱい。2007/05/29(火) 02:54:34
無理して一行でやるより、行舐めの回数が少ない方が好きだな。
0511名無しさん@お腹いっぱい。2007/05/29(火) 02:57:15
>>510 ワンパスだし。消費メモリを考えればいいと思うが。
0512名無しさん@お腹いっぱい。2007/05/29(火) 03:15:32
>>499
は論外。
0513名無しさん@お腹いっぱい。2007/05/29(火) 09:33:18
awk '{if (FNR>20) print a[FNR%20]; a[FNR%20]=$0}'
0514名無しさん@お腹いっぱい。2007/05/29(火) 10:12:43
20行分だけバッファして遅延して出力させて
ファイル末尾に到達したら終了させるとか。
0515名無しさん@お腹いっぱい。2007/05/29(火) 19:07:30
>>514
書いてみよう
0516名無しさん@お腹いっぱい。2007/05/29(火) 19:20:43
>>514
>>513 がやろうとした事(間違ってるがw)
0517名無しさん@お腹いっぱい。2007/05/29(火) 19:44:45
>>496
こういう場合、ed を non-interactive に使うのがいい。

最後20行ということは、$-19から $までだから、

echo '$-19,$d
w outfile
q' | ed infile

↑で桶。
0518名無しさん@お腹いっぱい。2007/05/29(火) 21:46:07
sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'|sed -e '$d'
0519名無しさん@お腹いっぱい。2007/05/30(水) 08:58:50
>>516 間違ってる?
0520名無しさん@お腹いっぱい。2007/05/30(水) 19:17:11
質問なんですが・・

#!/bin/sh -

tmpfile=/tmp/program.$$
cat "$1" | tr ' ' '\n' > tmpfile

while read word
do
grep ${word} "$2" | いろいろと処理・・・
done < tmpfile

てな感じのスクリプトなのですが、
第一引数のファイル中に、例えば -i と言うような語があると
grep がオプションと解釈するのか何なのか、直後に while ループが
終了してしまいます。
'${'"$word"'}' だと grep には ${word} として渡されてしまいます。

何とかシェルを騙して grep に '-i' として渡す方法は無いでしょうか?

(渡す前に条件判断して先頭文字が - なら sed などで先頭に \ を
付加すると言うのも行けそうな気はしますが、出来れば余計なIFとか
変数とか無しで行きたいものです)
0521名無しさん@お腹いっぱい。2007/05/30(水) 19:35:35
grep -e
grep -
05225202007/05/30(水) 19:53:07
>>521

ありがとう。
シェルを騙さなくても grep の方で用意されていましたか、
良く考えりゃ当然ですね。
0523名無しさん@お腹いっぱい。2007/05/30(水) 21:22:55
オプション -- で、それ以降はオプションとは解釈しないってのは
結構な数のコマンドで使える。
05245202007/05/30(水) 23:07:09
>>523

ですね。

これまで -- なんて、はぁ?って感じでしたけど、
実に有用性が高いですね。
勉強になります。
0525名無しさん@お腹いっぱい。2007/06/02(土) 11:43:37
質問
インターネットに接続できるか試すコマンドってありますか?

やりたいこと
インターネットに接続できたら echo "できます"
インターネットに接続できなかったら echo "できません"
としたいです。
0526名無しさん@お腹いっぱい。2007/06/02(土) 11:59:13
インターネットとLANの区別をしなくていいのかな?
0527名無しさん@お腹いっぱい。2007/06/02(土) 12:05:24
多分、この程度の精度でOKなんだろ。

if ping -c 1 www.yahoo.com >/dev/null 2>&1; then
echo "出来ます"
else
echo "出来ません"
fi
05285252007/06/03(日) 03:05:39
>>562>>527
ありがとうございます
できればヤフーなどの特定のサイトに依存せず
確実にインターネットに繋がるかどうか判断したいです。
もし無理なら特定のサイトでも構いませんが
こういう場合通例としてyahoo.comを使うのが適切でしょうか?
0529名無しさん@お腹いっぱい。2007/06/03(日) 07:09:14
接続できていると分かったら、どこかと通信するんでしょ?
その通信相手にすればいいよ。
0530名無しさん@お腹いっぱい。2007/06/03(日) 07:21:06
>>528
何が目的なん?
0531名無しさん@お腹いっぱい。2007/06/03(日) 08:59:25
その通信相手がICMPブロックしてるかも知れないから、ブロックしてない
www.yahoo.comとかwww.google.comとか使えばいい。
0532名無しさん@お腹いっぱい。2007/06/03(日) 11:01:00
>>528
君のほうから、どことつながったらインターネットに繋がっていると言えるかの
判断基準を出してくれないと先に進めないと思うよ。
0533名無しさん@お腹いっぱい。2007/06/03(日) 12:04:41
相手もそうだがプロトコルもな。
ファイアウォールの具合でICMP通らないかもしらんし。
0534名無しさん@お腹いっぱい。2007/06/03(日) 23:19:33
まぁ、スレ違いだな。
0535名無しさん@お腹いっぱい。2007/06/04(月) 07:59:35
>>527
>if ping -c 1 www.yahoo.com >/dev/null 2>&1; then

関係ないが、この 2>&1
エラー対策でつか?
0536名無しさん@お腹いっぱい。2007/06/04(月) 14:12:29
遅レスだが、

tail -r ファイル名| tail +20 | tail -r

でもいけた(tailばっかりでカッコ悪いか)
0537名無しさん@お腹いっぱい。2007/06/04(月) 21:46:12
>>535
終了ステータスだけとれりゃいいので、エラーメッセージとか捨てる。
0538名無しさん@お腹いっぱい。2007/06/04(月) 21:50:18
それを捨てるなんて、とんでもない!
0539ウサチャソ2007/06/04(月) 23:49:23
きのうはおたのしみでしたね。
ウホッ
0540名無しさん@お腹いっぱい。2007/06/04(月) 23:51:56
*「おお しんでしまうとは なにごとだ!」
*「アッー!」
0541名無しさん@お腹いっぱい。2007/06/05(火) 06:33:28
vmstat 1 の結果の左側に`date +%H:%M:%S`(時分秒)を付けて流して表示させようとしています。

以前、gawkでstrftimeを利用して同じ事をしたのですが、今回使ってるサーバのawkは
gawkでない為に別の方法が必要です。

どうもウマイ方法が思いつきませんで・・・ご教示お願いします。
0542名無しさん@お腹いっぱい。2007/06/05(火) 08:54:12
Perlあるなら
vmstat 1 | perl -MPOSIX -pe 'BEGIN{$|=1} print strftime q{%H:%M:%S }, localtime'
0543名無しさん@お腹いっぱい。2007/06/05(火) 08:59:20
これは重そうだけど
vmstat 1 | while read line; do echo `date +%H:%M:%S` $line; done
0544名無しさん@お腹いっぱい。2007/06/05(火) 20:13:14
>>539-540
DQ I ?
05455412007/06/05(火) 22:31:39
>>542
HP-UX10.20だったのですがperlが入っていませんでした(汗
でも、これを機会にperlもちょっとづつ勉強したいと思います。どもでした。

>>543
readがそんな使い方できるとは知りませんでした。
おかげさまでばっちり動きました。ありがとうございます。
0546名無しさん@お腹いっぱい。2007/06/05(火) 23:39:38
bash.infoの説明だと
echo hoge | read v

echo $V →hoge
になるように読める
で、できないってことはわかったんだけど結局readはどう使うんですか
なんでwhile中だとうまく動くんでしょう
0547名無しさん@お腹いっぱい。2007/06/06(水) 00:17:57
サブシェルが起動するから。
read で代入する変数はサブシェルのものだから、親シェルに戻ると忘れる。
while でなくても、下のような書き方をすれば {...} の中にかぎり有効。

echo hoge | {
read v
echo $v
}

あと、ksh はふつーに可能だったような記憶がうっすらとあるが自信ない。
0548名無しさん@お腹いっぱい。2007/06/06(水) 15:14:41
質問
シェルスクリプトを、windowsでCD-Rに焼き、linuxで実行すると
改行がコマンドとして認識され、command not foundとなってしまいます。
普通に改行を改行として認識させることはできないのでしょうか?
0549名無しさん@お腹いっぱい。2007/06/06(水) 16:33:41
よくわからんが改行コードの問題? 改行コードをLFで保存できるテキストエディタ使えよ
0550名無しさん@お腹いっぱい。2007/06/06(水) 16:52:46
>>549
ありがとうとざいます
LFで保存したところ大丈夫でした。
ただし1行目だけはなぜかcommand not foundとなってしまう。。
0551名無しさん@お腹いっぱい。2007/06/06(水) 20:15:14
log=20070101.log

$logを 2007-01-01
という風に、[西暦]-[月]-[日]な形にしたいのですが、どすればよいでしょうか?
どなたか、お力をお貸し下さいませ。

.log と取って、4桁、2桁、2桁ごとに「-」を挟む。というのはわかるのですが
方法や何のコマンド使ってよいものやら見当もつきません。お願いします!
0552名無しさん@お腹いっぱい。2007/06/06(水) 20:26:09
echo $log | sed 's/\(....\)\(..\)\(..\).*/\1-\2-\3/'
0553名無しさん@お腹いっぱい。2007/06/06(水) 20:30:18
>>552 ありがとうございました!出来ました!
sedは使えるつもりでいたんですが、まだまだの若輩者でしたorz
こんなに早く答えて頂いて本当に助かりました。
0554名無しさん@お腹いっぱい。2007/06/06(水) 23:42:52
じぇっとすとりーーーむ〜
0555名無しさん@お腹いっぱい。2007/06/06(水) 23:42:59
シェルが何かは分かったのですが、シェルスクリプトが良く分かりません…

専門用語を交えないで言うと、どういったものなのでしょうか?
0556名無しさん@お腹いっぱい。2007/06/06(水) 23:44:51
シェルが何かどうわかったか、専門用語を交えずに説明してからだ
0557名無しさん@お腹いっぱい。2007/06/07(木) 00:11:41
レストランのメニューがシェル。コース料理がシェルスクリプト。
大分違うな…
0558名無しさん@お腹いっぱい。2007/06/07(木) 00:35:32
http://e-words.jp/w/E382B7E382A7E383ABE382B9E382AFE383AAE38397E38388.html

専門的な概念なのに専門用語使うなというのは無理な話。
0559名無しさん@お腹いっぱい。2007/06/07(木) 02:08:21
>>557

その説明で開眼しました!!

今ならどんなプログラムも書けそうです!!
(^ω^)
0560名無しさん@お腹いっぱい。2007/06/08(金) 00:50:30
if [ -e foo ] ;
then
echo "foo exists."
else
echo "foo does not exist."
fi
これを Solaris 8の bash, cygwinの sh, bashで実行するとOK。
でも Solaris 8の shで実行した時だけ
test: argument expected
と出てしまいます。どうにも分かりません。助けて下さい…

0561名無しさん@お腹いっぱい。2007/06/08(金) 03:13:50
Solarisなどの旧式shのtestコマンドには-eというものはない。
これは外部コマンドのtestも同様。
0562名無しさん@お腹いっぱい。2007/06/08(金) 06:27:46
>>561
ダウト。
Solarisの外部コマンド版のtestの実体はkshスクリプトだから、
Solarisでも外部コマンド版のtestには -eオプションがある。

ただし、純正Bourneには -eがないので、使わないこと推奨なのは同意。
[ -f foo ] あたりで代用だな。
0563名無しさん@お腹いっぱい。2007/06/08(金) 08:29:58
grepコマンドで検索した行の前後三行を出力するコマンドってないすか?

たとえば、以下のようなファイルがある。
----------------------------
aaa
bbb
ccc
ddd
eee
fff
ggg
----------------------------

grepコマンドをつかって、
$ grep ddd -a 333
とすると
bbb
ccc
ddd
eee
fff
と表示されるようなやつよ。
0564名無しさん@お腹いっぱい。2007/06/08(金) 08:45:56
>>563
-A とか -B とかない?
0565名無しさん@お腹いっぱい。2007/06/08(金) 10:35:48
>>563
普通にgrepだけで行けるぞ
grep -A 3 -B 3 'ddd' filename
0566名無しさん@お腹いっぱい。2007/06/08(金) 10:44:10
普通は-Aとか-Bなんてない。
0567名無しさん@お腹いっぱい。2007/06/08(金) 11:01:46
何が「普通」かなんて人それぞれでしょ。
-A がある grep とない grep がある。
それだけ。
0568名無しさん@お腹いっぱい。2007/06/08(金) 11:02:54
目的達成できるなら、それでいいじゃん
0569名無しさん@お腹いっぱい。2007/06/08(金) 11:03:45
grep -n して
sedで : より前だけ取り出して
awkにくべて前後の必要な行番号を全部計算して
sort -nuして
sedでsedのコマンドに成形しなおして
sedで抽出。
てゆうか、grepにこだわらずにawk1個の方がめちゃ楽そう。
0570名無しさん@お腹いっぱい。2007/06/08(金) 11:04:44
>>569
awkだけだとどうなるの?
0571名無しさん@お腹いっぱい。2007/06/08(金) 11:29:37
FreeBSDは変にsed使うよりawk1本に絞った方が軽い。
0572名無しさん@お腹いっぱい。2007/06/08(金) 11:43:53
複数行のテキスト整形には弱い
普通は、prelとかrubyを使う
まあ、perlとかruby使えないから聞いてるんだろうけど
0573名無しさん@お腹いっぱい。2007/06/08(金) 11:52:15
>>572
sedやgrepでどうしようかななんて考えてる時間が無駄だよな
perl覚えちゃたほうがいいのにね、これを機会に
0574名無しさん@お腹いっぱい。2007/06/08(金) 11:55:16
これを機会にGNU grep入れちゃえ。
0575名無しさん@お腹いっぱい。2007/06/08(金) 12:00:44
パタン行より前の行も表示しないといけないのでawk一本だとちょっと手間でしょ。
perlやrubyを使ってもそれは同じじゃないかな。
sed+awkなら
sed -e "$(awk '/pattern/{for (i=-2;i<=2;i++)if(i+NR>=0)print (i+NR) "{p;d;}"}' file|sort -nu)"';d' file

zshでしか試してないのでクォート回りはshだと違うかも知れんが、
だいたいこんな感じで。
0576名無しさん@お腹いっぱい。2007/06/08(金) 12:19:38
GNUは偉大だな、改めて思った
0577名無しさん@お腹いっぱい。2007/06/08(金) 12:26:01
当たり前じゃね?
だってGNU拡張は、ユーザが便利だと思うものを実装して
拡張していったんだから

きっと、>>563みたいなことを、数年前にも同じといってる人が
現れてんだよw
それで拡張されてる
0578名無しさん@お腹いっぱい。2007/06/08(金) 12:40:49
GNU sed awk grep を使いましょうね
0579名無しさん@お腹いっぱい。2007/06/08(金) 15:54:55
俺はgawk派
0580名無しさん@お腹いっぱい。2007/06/08(金) 16:04:21
ガウォーク
0581名無しさん@お腹いっぱい。2007/06/08(金) 16:14:46
GNU is Not UNIX
の意味がやっとわかったようでなにより
0582名無しさん@お腹いっぱい。2007/06/08(金) 16:21:47
んでけっきょく >>563 はどうしたの?
0583名無しさん@お腹いっぱい。2007/06/08(金) 16:25:28
GNU教に入信する準備をしてます
0584名無しさん@お腹いっぱい。2007/06/08(金) 16:29:28
しこしこ、書いてんじゃね
0585名無しさん@お腹いっぱい。2007/06/08(金) 17:38:00
mac でターミナルで操作しているのですが、safariでgoogleなどのページで
キーワードを打ち込んで検索させたりはできないものなんでしょうか?
初心者なんで仕組みなどわかりませんので構造上できないものなら教えてください
0586名無しさん@お腹いっぱい。2007/06/08(金) 17:49:58
>>585
http://pc11.2ch.net/mac/
0587名無しさん@お腹いっぱい。2007/06/08(金) 21:02:22
シェルスクリプトとGUIアプリの連携ってか?
0588名無しさん@お腹いっぱい。2007/06/08(金) 22:41:28
質問です!
---hoge.txt---
aaa
bbb
ccc

これを

---hoge.txt---
aaa
ccc

こうしたい。

sed -i "s/bbb//g" hoge.txtだと

---hoge.txt
aaa

ccc

こうなってしまう・・・
0589名無しさん@お腹いっぱい。2007/06/08(金) 22:49:06
sed -i -e '/bbb/d'
■ このスレッドは過去ログ倉庫に格納されています