トップページunix
1001コメント301KB

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

レス数が950を超えています。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 でトレースしましょう。
0872名無しさん@お腹いっぱい。2007/02/07(水) 13:13:10
マジレスはご遠慮ください。
0873名無しさん@お腹いっぱい。2007/02/07(水) 13:13:55
マジレス上等
ゴマエー
0874名無しさん@お腹いっぱい。2007/02/07(水) 13:22:21
>>859がダメ人間(かどうかは知らん)という命題と、>>858がダメ人間(これは確実)
という命題はは排他ではない。
0875名無しさん@お腹いっぱい。2007/02/07(水) 13:27:51
ははは 可愛い奴だなぁ
08768312007/02/07(水) 15:31:42
>>868
そうそう、まさにそのとおり。
俺もそんなやり方でやっている。
viとかpicoとかでは>>868のような処理はできんだろ。

意味分かる?w
0877名無しさん@お腹いっぱい。2007/02/07(水) 15:55:26
$ < hoge cat
...出力...
$ < 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:36
コマンドを作り上げていく過程での話なら、好きにすればいいじゃん。


0880名無しさん@お腹いっぱい。2007/02/07(水) 16:33:11
cat hogeから始める必要は全然無い。

$ 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:25
どうしよう、>>859 のダメ度がどんどん進行しちゃう
0882名無しさん@お腹いっぱい。2007/02/07(水) 16:56:48
ダメなのは >>858
0883名無しさん@お腹いっぱい。2007/02/07(水) 18:05:59
<span></span>の中のhtmlタグを消したいのですが、いい手はないでしょうか?
sed -n か awk を使えばできると思うのですが難しいです。

<span>
数行
</span>
数行
<span>
数行
</span>
0884名無しさん@お腹いっぱい。2007/02/07(水) 18:19:17
>>883
>>743
08858312007/02/07(水) 18:50:30
>>842
今日、仕事をサボって(w)
本屋に行ってきて物色してみました。
Rubyがよさげだったので
さっそく「たのしいRuby」という本を
買ってきました。
ttp://sheel.mydns.jp/~sheel/ruby.jpg

ワクワクしますよ。
0886名無しさん@お腹いっぱい。2007/02/07(水) 20:54:51
あたえられる文書が整形式のXMLの形になっているなら、
xmlstarlet とかのツールを補助に使えばいいと思うよ。
XSLT でも Xpath でも好きにコマンドラインから使える。
0887名無しさん@お腹いっぱい。2007/02/07(水) 22:52:08
>>883
<span> と </span> のが完全に1行ずつなら簡単だね
0888名無しさん@お腹いっぱい。2007/02/07(水) 22:55:59
>>887
そのように整形する前処理をするとかね
08898312007/02/08(木) 09:49:41
>>883
おれなら
cat -nとかでhtml書類を出力し
それをパイプしてgrepなどで一番最初に遭遇する
<span>と</span>をみつけ、
cut -d¥: -f1を使ってその行頭の数値(=行番号)をよみとり、

その結果をまた

それをパイプしてgrepなどで一番最初に遭遇する
<span>と</span>をみつけ、
cut -d¥: -f1を使ってその行頭の数値(=行番号)をよみとり、

という繰り返しでやるかな。
08908312007/02/08(木) 10:05:40
まちがいた・・・orz
>>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
まぁ大抵の用途では「CDATAセクションに</span>がありました」
なんてケースは考えるだけ無駄だったりするよな。
0892名無しさん@お腹いっぱい。2007/02/08(木) 11:26:21
そう?
RSSとか扱ってると、結構あるけど
0893名無しさん@お腹いっぱい。2007/02/08(木) 11:30:47
その辺の要求仕様は本来なら質問者が書くべきだと思うんだが
たいていこういう質問投げるやつって投げっぱなしだよね。
0894名無しさん@お腹いっぱい。2007/02/08(木) 12:14:03
RSSはXMLのくせにwell-formedなんてくそくらえって感じの世界が……
08958832007/02/08(木) 14:59:16
自己解決しました
0896名無しさん@お腹いっぱい。2007/02/08(木) 16:26:18
ihsのログのローテーションについてのシェルで、次の2つのif文をfor文にまとめて書く書き方
知っているかた教えてください。

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:50
for log in access_log error_log; do
if [ -e /work/IBMIHS/logs/$log ];
then
else
fi
done
0899名無しさん@お腹いっぱい。2007/02/08(木) 17:13:19
シェルってゆうな

for f in access_log error_log; do ....
ってことをしたいのか?
0900名無しさん@お腹いっぱい。2007/02/08(木) 17:17:12
IHSというかapacheのログってmvではローテーションできないんじゃなかったっけ?

ま、それはおいといて、単純に繰り返し部分をまとめるだけなら、

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:12

for FN in "access_log" "error_log"
0902名無しさん@お腹いっぱい。2007/02/08(木) 19:58:24
シェルスクリプトとちょっとずれるかもしれないのですが、
sudo -u hoge echo "hoge" > test.txt
とすると
test.txt の所有権は hoge ではなく、
sudo の実行者になります。

test.txt を hogeの所有権のファイルとして作成したいのですが、
どこに間違いがあるかご教授お願いします。
0903名無しさん@お腹いっぱい。2007/02/08(木) 20:05:21
リダイレクトは sudo の実行前にシェルが解釈する。

sudo -u hoge sh -c 'echo "hoge" > test.txt'
0904名無しさん@お腹いっぱい。2007/02/08(木) 20:07:16
シェルがコマンドラインを受理した際、
1. > test.txt
2. sudo -u hoge echo "hoge"
の順で処理されるからね。

sudo -u hoge sh -c 'echo "hoge" > test.txt'


09059022007/02/08(木) 20:09:21
>>903
レスありがとうございます、
上の内容をためしたところ、存在しない、といったエラーが出てしまいました。
お助けを〜〜
sh: test.txt: No such file or directory
09069022007/02/09(金) 01:44:34
すいません、何か激しくボケていたようです。
再度試してみたらいけました。
ありがとうございました。
教えていただいた内容も納得です!

ちょっと関連した内容になるのですが、
"hoge"の部分に改行などを含んだ変数を入れたいのですが、
うまくいきません。
どうやら改行ごとに、シェルが実行されてしまっている?ようです。
複数行にわたった変数を使用したい場合、
どのように記述すればよいでしょうか?

何度もすいません orz
0907名無しさん@お腹いっぱい。2007/02/09(金) 06:43:27
改行を\でエスケープすれば効くかも。
0908名無しさん@お腹いっぱい。2007/02/09(金) 10:17:57
シェルによっては、echo "hogeの直後に改行すると、"を認識してそのまま
継続行を入力させてくれるかも。
0909名無しさん@お腹いっぱい。2007/02/09(金) 11:38:06
>>906
何もする必要ない。"hoge" の途中に改行があっても改行はそのまま保存される。
もし、そうならないなら、sudoを実行しているコマンドラインのシェルが、
普通のB-sh系のシェルじゃないんだろう。
(あるいは、sudo先のユーザーのログインシェルが B-sh系じゃないとか)
sh bash zsh ksh 等の B-sh系を使うこと。
09109022007/02/09(金) 15:59:08
そうですか・・・・
レスありがとうございます。

ある変数の内容をファイルに書き込みたい、
という場合、echo とリダイレクトを使う以外にありますでしょうか?
0911名無しさん@お腹いっぱい。2007/02/09(金) 16:04:07
↓これで委員じゃないか?

echo "$変数" | sudo -u hoge sh -c 'cat > test.txt'

sudo先のshでechoすると、クォートが2重になってややこしいから、
sudo前にechoしておいてパイプでつなぐ。
09129022007/02/09(金) 16:30:53
>>911
orz ありがとうございます、うまくいきました。
クオートが入れ子になってて鬱入ってました。
発想の転換ですね、さすがみなさん視点がすごいです!!

本当にありがとうございました!!!
0913名無しさん@お腹いっぱい。2007/02/11(日) 17:22:09

「ls -l」形式のファイル一覧が入っているテキストファイル(引数)
を1行ずつ読み込み、ファイル名に「.bak」が含まれるファイルを
消去するシェルスクリプトを作成したいのですが、頭の「#!/bin/sh」
を書いた時点で力尽きました。

「while read」を使う、というところまでは理解出来たのですが、
文法等がさっぱりで…どなたかご教授願えないでしょうか?
0914名無しさん@お腹いっぱい。2007/02/11(日) 17:33:05
>>913
read 使うと逆に難しそう。
grep .bak したのを sed か awk かなんかで加工して rm、がいいと思う。

> 「ls -l」形式のファイル一覧が入っているテキストファイル(引数)
この前提は変えられない?
ls -l 形式は扱いづらそうだから
find とか使った方がいいと思うんだが。
0915名無しさん@お腹いっぱい。2007/02/11(日) 17:37:27
>>913
超簡単。1行で書ける。

while read line; do case $line in *.bak);; *) echo "$line";; esac; done < file

>>914
おまえには難しかったようだね。
0916名無しさん@お腹いっぱい。2007/02/11(日) 17:48:12
>>915
それって >>913 の要求満たしてるの?
0917名無しさん@お腹いっぱい。2007/02/11(日) 17:50:39
「ls -l出力が書かれたファイルの中から、ファイル名 *.bakの行だけ消去する」のか、
「ls -l出力が書かれたファイルの中から、ファイル名 *.bakのファイルを消去する」 のか?
0918名無しさん@お腹いっぱい。2007/02/11(日) 17:53:13
>>917
わかりにくい質問でどうも済みませんでした。
前者の意味です。>>915 でできました。Thanksです。
0919名無しさん@お腹いっぱい。2007/02/11(日) 17:54:48
rm したいんじゃなかったのか。
なら grep -v '\.bak$' でいいじゃん。
シンボリックリンクに対応してないけど。
09209132007/02/11(日) 18:02:01

申し訳ありません。説明不足でした。
「ls -l出力が書かれたファイルの中から、ファイル名 *.bakのファイルを消去する」
が目的です。

ファイルリストをgrepして*.bakを含む行だけ取り出した後、awkを使用してls -lの
リストからファイル名を抜き出して…とか色々と考えていたのですが、それらを
シェルスクリプトで作成するだけの知識とか度胸とかが足りなくて困っております。

>915
回答ありがとうございます。「esacって何?」とか調べていたら返事が遅れて
しまいました。
0921名無しさん@お腹いっぱい。2007/02/11(日) 18:03:46
これ宿題だよなって言ったら
0922名無しさん@お腹いっぱい。2007/02/11(日) 18:04:52
けっきょくどっちなんだ・・・
0923名無しさん@お腹いっぱい。2007/02/11(日) 18:06:10
>>920
だったら、↓で行ける。(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
0924名無しさん@お腹いっぱい。2007/02/11(日) 19:34:21
hoge.bakなんつーディレクトリがある可能性があるならtestも入れる。
0925名無しさん@お腹いっぱい。2007/02/11(日) 19:50:26
まずは
cat file |sed -e
09269132007/02/11(日) 19:56:38
>923
回答ありがとうございます。色々いじくり回して実験してみます。
0927名無しさん@お腹いっぱい。2007/02/11(日) 23:23:51
file の更新時間が今の何日前かを表示したいのですが、良い案はないでしょうか?
アバウトに日付情報だけで判断できれば十分なので
find file -printf "%Ad" でやろうと思ったのですが
月をまたぐとどうにもこうにもいきません。
0928名無しさん@お腹いっぱい。2007/02/11(日) 23:39:08
>>927
OSによってはdateとかを駆使してもできるとは思うが、perlが適材適所
0929名無しさん@お腹いっぱい。2007/02/11(日) 23:41:54
%コマンド XXX ./AAA/

とやって、
ファイルXXX をディレクトリAAA にコピー(cp) して
なおかつ、AAA に移動(cd) する

というコマンドを作りたいんだけど、どうすればいい?
0930名無しさん@お腹いっぱい。2007/02/11(日) 23:48:39
aliasかfunctionを使う
0931名無しさん@お腹いっぱい。2007/02/12(月) 00:14:22
>>929
.bashrc あたりにこんな感じの function を書くのがお手軽かな

hoge(){
 cp "$1" "$2"
builtin cd "$2"
}

引数のチェックとかの拡張はお好みで。
0932名無しさん@お腹いっぱい。2007/02/12(月) 00:27:49
>>929は%だからcsh系じゃないのか?と勝手に予想
0933名無しさん@お腹いっぱい。2007/02/12(月) 01:36:07
どっちかというとBourneシェル系であるzshのデフォルトも%だったりして。
0934名無しさん@お腹いっぱい。2007/02/12(月) 02:10:57
っていうか tcsh ならデフォルトは > なので。
0935名無しさん@お腹いっぱい。2007/02/12(月) 11:09:31
>>933
>>934
そうだったのかー
0936名無しさん@お腹いっぱい。2007/02/12(月) 11:46:56
で、>>929が使ってるシェルは何なの?
0937名無しさん@お腹いっぱい。2007/02/12(月) 12:00:01
tcshをargv[0]がcshで起動するとプロンプトは%
0938名無しさん@お腹いっぱい。2007/02/12(月) 12:33:37
>>929
bashだろ、どうせ。
09399292007/02/12(月) 22:02:42
返事が遅くなりました
tcsh です
0940名無しさん@お腹いっぱい。2007/02/13(火) 00:32:06
>>929
cshスクリプトを書いておいて、
それをsourceするaliasを設定するとか。

もっとスマートな方法、教えてエロい人。
0941名無しさん@お腹いっぱい。2007/02/13(火) 03:40:49
蟹飯先生謹製のawkを落としてみたが、UTF-8で日本語が通る。
シンボリックリンクをgawkから変更しようかしら。
最近のgawkはインターネットアクセスが出来るらしいけど使いかたが分からない。
0942名無しさん@お腹いっぱい。2007/02/13(火) 06:38:22
>>941
日本語が「通る」の意味がよくわからないが、
.がちゃんと一文字に適合したり
文字クラスとして[あ-ん]のようなものが書けたり
\u3120のようにユニコードリテラルを記述できたりするの?
0943名無しさん@お腹いっぱい。2007/02/13(火) 07:18:58
>>942
そのへんは検証してもらえないかなと思いまして。w
とりあえず.は駄目でした。w
[あ-ん]はたぶん大丈夫そうな気が。
4行目の機能ってgawkにあるんですか?
0944名無しさん@お腹いっぱい。2007/02/13(火) 07:45:46
>>943
いや別にgawkは関係ない。
せっかくUnicodeに対応しているなら、出来たほうが便利なのは
確実だが。
"Tibetan"とか"Greek"とか"CJKCompatibility"みたいに、
Unicodeのブロック/カテゴリ名が使えるとさらによい。

逆にその辺が出来ないなら、今時のUnicode対応としては
大したこと無いレベルじゃまいか?
まー今更awkにそんなに多くを求めてもしゃーない気はするが。
0945名無しさん@お腹いっぱい。2007/02/13(火) 07:48:10
.が一文字に適合しないのなら、文字クラス指定も駄目っぽそうだな。
単に8bitクリーンなだけじゃないの?
0946名無しさん@お腹いっぱい。2007/02/13(火) 08:25:37
どうやらそのようですね。
...(.が3回)で一文字に適合しました。w
0947名無しさん@お腹いっぱい。2007/02/13(火) 14:47:36
dir="aaa bbb"
for f in $dir;do
echo "$f"
done
とすると
aaa
bbb
と表示されますが、この dir に空白を含む文字列を含ませるにはどうすればいいのでしょうか?
イメージとしては
dir='aaa bbb "ccc ddd"' とすると
aaa
bbb
ccc ddd
と表示できたらいいなと
0948名無しさん@お腹いっぱい。2007/02/13(火) 18:30:35
>>947
できないはず
だからperlにしろと
0949名無しさん@お腹いっぱい。2007/02/13(火) 19:00:25
>>947
そういう場合は位置パラメータを使う。

set aaa bbb 'ccc ddd'

for f in "$@"; do
echo "$f"
done

これで、
aaa
bbb
ccc ddd
と表示される。
0950名無しさん@お腹いっぱい。2007/02/13(火) 20:24:33
「できないはず」と答えてしまった >>948 が不憫。
09519292007/02/13(火) 21:04:24
>>940

alias 使えばいいというのはわかるんですが、
そのcsh スクリプトがかけないんです
0952名無しさん@お腹いっぱい。2007/02/13(火) 21:06:59
>>951
cshの話は厳禁。よそ行け。
b-shでの答えはすでに出てる。
0953名無しさん@お腹いっぱい。2007/02/13(火) 21:38:37
for aa in aaa bbb ccc\ ddd; do echo $aa; done;
0954名無しさん@お腹いっぱい。2007/02/13(火) 21:38:56
いつもの人キタ━(゚∀゚)━!!
0955名無しさん@お腹いっぱい。2007/02/13(火) 21:43:14
>>953 は元の質問の意味がわかってない。
0956名無しさん@お腹いっぱい。2007/02/13(火) 22:58:21
>>951
$HOME/tmp/cpcd.shとかを作って中身を
#!/bin/tcsh
cp "$1" "$2"
cd "$2"
として、
chmod +x $HOME/tmp/cpcd.sh
alias cpcd "source $HOME/tmp/cpcd.sh"
0957名無しさん@お腹いっぱい。2007/02/13(火) 23:25:57
単体で起動しても意味ないしsourceするんだから
sh-bangも+xもいらないんじゃないか?
0958名無しさん@お腹いっぱい。2007/02/14(水) 01:24:40
ファイル名を"abc.txt"から日付+d.txtにリネームしたいのですがうまくいきません。
対処法を伝授して下さい

mv abc.txt %Y%m%dd.txt
0959名無しさん@お腹いっぱい。2007/02/14(水) 01:44:50
>>943
>4行目の機能ってgawkにあるんですか?

ない。

gawkは内部的にwchar_tを使っているだけで、スクリプトの記述は
そのときの locale設定が使われ、表にはUnicode(やwchar_t)はでてこない。

一応 [あ-お]はできるけどね。

0960名無しさん@お腹いっぱい。2007/02/14(水) 01:48:59
>>958
mv abc.txt `date +%%Y%m%d`d.txt
0961名無しさん@お腹いっぱい。2007/02/14(水) 01:50:00
%一つ余計だ。察して。
09629582007/02/14(水) 01:52:02
>>960
ありがとうございます。うまくいきました
0963名無しさん@お腹いっぱい。2007/02/14(水) 03:16:18
jawk
09649472007/02/14(水) 03:20:49
>>949

ありがとう
0965名無しさん@お腹いっぱい。2007/02/14(水) 08:07:50
ttp://www.postfix-jp.info/trans-2.2/jhtml/FILTER_README.html
の上のほうにあるスクリプトのtrapって何を拾っているんでしょうか?
0 は分かるんですが、1, 2, 3, 15が分かりません。
0966名無しさん@お腹いっぱい。2007/02/14(水) 09:19:02
>>965
man 7 signal参照。
1:SIGHUP 2:SIGINT 3:SIGQUIT 15:SIGTERM
0967名無しさん@お腹いっぱい。2007/02/14(水) 10:12:04
>>966
$ man 7 signal
No entry for signal in section 7 of the manual

ここはLinux板じゃない。
0968名無しさん@お腹いっぱい。2007/02/14(水) 13:32:31
cron?
0969名無しさん@お腹いっぱい。2007/02/14(水) 13:33:04
みす
0970名無しさん@お腹いっぱい。2007/02/14(水) 13:54:30
>>966-967
man -a signalと言っておけばよかったね。

BSD(つーかMacだが)だとセクション3のライブラリ関数のとこに
一緒に載ってるようだな。
0971名無しさん@お腹いっぱい。2007/02/14(水) 15:13:05
bash起動してtrap -lはどうか。
0972名無しさん@お腹いっぱい。2007/02/14(水) 22:52:51
ls で ディレクトリのみ表示させるのは可能でしょうか?
レス数が950を超えています。1000を超えると書き込みができなくなります。