シェルスクリプト総合 その7
■ このスレッドは過去ログ倉庫に格納されています
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 でトレースしましょう。
0716名無しさん@お腹いっぱい。
2007/01/12(金) 01:52:33flowers(花言葉)とかbirthtoken(誕生石)とか、妙なファイルもあるんだな。
0717名無しさん@お腹いっぱい。
2007/01/12(金) 01:55:54お、ほんとだ
なんでもあるな
0718名無しさん@お腹いっぱい。
2007/01/12(金) 01:57:43なるほど
でもそのファイルにNeXTの話がないのが微妙
0719名無しさん@お腹いっぱい。
2007/01/12(金) 17:59:42UNIXのファイルシステム上だと
(rm hoge.dat; sed 's/aaa/bbb/' > hoge.dat) < hoge.dat
でOK
0720名無しさん@お腹いっぱい。
2007/01/12(金) 18:11:02なるほど
0721名無しさん@お腹いっぱい。
2007/01/12(金) 18:31:570722名無しさん@お腹いっぱい。
2007/01/12(金) 19:50:060723名無しさん@お腹いっぱい。
2007/01/12(金) 20:44:541. < hoge.dat
ファイルディスクリプタを確保する。(&標準入力にする)
このディスクリプタが開いている限り、ファイル名がなくなっても
ファイルの実体は消えない。
2. (...)
サブシェルを起動する。ファイルディスクリプタは継承される。
3. rm hoge.dat
hoge.datというディレクトリエントリ(ファイル名)を消す。
しかし、それが指していた実体は1.のディスクリプタからまだ参照
されているため、消えない。
4. >hoge.dat
別途hoge.dat という名前でファイルを開く。(&標準出力にする)
これは、もとのhoge.datが指していた実体とは別のディスク領域に書かれる。
5. 全体が終了すると、ファイルディスクリプタが閉じ、もとのファイル実体
が使っていたディスク領域が未使用状態とみなされる。
0724名無しさん@お腹いっぱい。
2007/01/13(土) 01:27:34(...)じゃなくて{...;}じゃダメ?
0725名無しさん@お腹いっぱい。
2007/01/13(土) 02:33:57自分でまずやってみろよ
0726名無しさん@お腹いっぱい。
2007/01/14(日) 01:54:35確かにpowerpc-apple-darwin8.0のbash 2.05b.0(1)-releaseでは`builtin`で呼び出せることも確認しました
一方で/bin/[や/bin/testも存在し、当然実行可能でした
また、若干の差異はありますが、複合コマンド(compound command)の`[[ expression ]]`もほぼ同じ用途に利用できます
そこで質問なんですが、少し上で話されていたような処理の重さ(無駄なプロセスの生成等)を考えた場合、
どれを使うのがベストなんでしょう?
0727名無しさん@お腹いっぱい。
2007/01/14(日) 02:03:12つーか、パフォーマンス重視な場合は
シェルスクリプトなんか使うな。
0728名無しさん@お腹いっぱい。
2007/01/15(月) 02:32:27という感じで、アクセスログから、特定のURLを探して数を数えて、その数をファイルに書き込んでいるのですが、これを毎日やると、
10
20
10
15
といった感じで、改行されてしまいます。
これを
10,20,10,15
という風に、,区切りにするにはどうすればよいでしょうか?
0729名無しさん@お腹いっぱい。
2007/01/15(月) 03:50:32tr -d '\n' < filea | sed -e 's/[ ]\{1,\}/,/g'
的な
0730名無しさん@お腹いっぱい。
2007/01/15(月) 03:56:110731名無しさん@お腹いっぱい。
2007/01/15(月) 03:56:540732名無しさん@お腹いっぱい。
2007/01/15(月) 06:03:29hoge.datというファイルがあるとして、
その中身が以下のようであったとします。
aaa
これを、
aaa
bbb
ccc
のように変更したいのです。
で、sedでこれを実現しようとする場合、
#!/bin/sh
sed 's/aaa/aaa \
bbb \
ccc/' hoge.dat
exit 0
こんな感じになると思います。
シングルコーテーションのとこがダブルコーテーションの場合は、
#!/bin/sh
sed "s/aaa/aaa \\
bbb \\
ccc/2 hoge.dat
exit 0
のように、\マークがふたつになると思います。
どうして、シングルコーテーションの場合は、\マークがひとつで、
ダブルコーテーションの場合は、\マークがふたついるのでしょうか?
よろしく呉教授お願いします。
0733名無しさん@お腹いっぱい。
2007/01/15(月) 06:36:10呉智英?なんてね
0734sage
2007/01/15(月) 09:21:26リアルで引いた。
0735名無しさん@お腹いっぱい。
2007/01/16(火) 23:37:40シングルクオートの場合はシェルに持ってかれないので\一つでOK。
こんな感じでシェルを介さなければ\一つでいける。
> cat replace.sed
s/aaa/aaa \
bbb \
ccc/
> sed -f replace.sed hoge.dat
aaa
bbb
ccc
>
SH(1)
> Double Quotes
> Enclosing characters within double quotes preserves the literal
> meaning of all characters except dollarsign (`$'), backquote
> (``'), and backslash (`\'). The backslash inside double quotes
> is historically weird. It remains literal unless it precedes the
> following characters, which it serves to quote:
> $ ` " \ \n
0737名無しさん@お腹いっぱい。
2007/01/18(木) 05:23:42以下のHTMLファイルがあるとします。
------------------------
<html>
<body>
<!--
memo
-->
hoge
</body>
<html>
------------------------
これを、以下のように<!--から-->の部分を削除したいのです。
------------------------
<html>
<body>
hoge
</body>
<html>
------------------------
このようなことをしたい場合、シェルスクリプトではどのようにすればよいでしょうか?
ちなみに、うちの会社の吉田さん曰く「そんなのawk使えば一発だよ!」といってました。。
0738名無しさん@お腹いっぱい。
2007/01/18(木) 07:34:59awkでもできるがsedを使うのが普通の感覚じゃね?
もちろん、後出しで仕様が複雑にならなければの話だけどな。
ちなみにsed的には/^<--/,/^-->/dとかだけど。
0739名無しさん@お腹いっぱい。
2007/01/18(木) 07:59:25違うよ。
0740名無しさん@お腹いっぱい。
2007/01/18(木) 09:02:41仕様はHTMLの文法通りと考えるべきだろ。後出しでも何でもない。
よって >>738 はその意味でも間違い。
0741名無しさん@お腹いっぱい。
2007/01/18(木) 09:15:58シェルスクリプトでやろうというのが間違いだな。
0742名無しさん@お腹いっぱい。
2007/01/18(木) 10:12:38つ「最長一致」
0743名無しさん@お腹いっぱい。
2007/01/18(木) 10:39:360744名無しさん@お腹いっぱい。
2007/01/18(木) 17:58:56bashでやってみました
#!/bin/bash
OLDHTML=$1
NEWHTML=$2
COMMENT=0
while read LINE
do
while echo $LINE | grep -q '<!--.*-->'
do
PARTLINE=${LINE%%<!--*}
LINE=$PARTLINE${LINE#*-->}
[ ! $LINE ] && continue 2
COMMENT=0
done
if echo $LINE | grep -q '<!--'; then
LINE=${LINE%<!--*}
[ $LINE ] && echo $LINE >> $NEWHTML
COMMENT=1
elif echo $LINE | grep -q '¥-->'; then
LINE=${LINE#*-->}
[ $LINE ] && echo $LINE >> $NEWHTML
COMMENT=0
elif [ $COMMENT -eq 0 ]; then
echo $LINE >> $NEWHTML
fi
done < $OLDHTML
0745名無しさん@お腹いっぱい。
2007/01/18(木) 18:18:42真面目にやるなら、htmlパーサ使っとけってこった。
0746名無しさん@お腹いっぱい。
2007/01/18(木) 18:27:230747名無しさん@お腹いっぱい。
2007/01/18(木) 19:02:080748名無しさん@お腹いっぱい。
2007/01/18(木) 19:07:10たぶんみんな別人だと思うぞ
0749名無しさん@お腹いっぱい。
2007/01/18(木) 21:30:050750吉田
2007/01/18(木) 23:57:28とくに>>744は茶ふいたわ。
>>737のいっているHTMLファイルを仮に、index.htmlというファイルとすると、
cat index.html | awk '/^<!--/,/^-->/ {next} {print}'
こうやればOK。
ばーか!
0751名無しさん@お腹いっぱい。
2007/01/19(金) 00:04:340752名無しさん@お腹いっぱい。
2007/01/19(金) 00:06:250754吉宗
2007/01/19(金) 00:09:270756徳田
2007/01/19(金) 00:14:200757名無しさん@お腹いっぱい。
2007/01/19(金) 00:15:09とりあえずばけらさんとこでも読んどけ
で>>737は本気で回答がほしければ
全ての形式のHTMLコメントを除去したいのか
>>737の形式のコメントを除去したいのか補足しろ
ってことでしょ
前者ならシェルスクリプト向きじゃないけど
0760名無しさん@お腹いっぱい。
2007/01/19(金) 00:27:54で、>>757はどっちなんだ?
0761名無しさん@お腹いっぱい。
2007/01/19(金) 17:31:080762名無しさん@お腹いっぱい。
2007/01/19(金) 19:32:180763名無しさん@お腹いっぱい。
2007/01/25(木) 13:51:51起動する前に好きなウィンドウマネージャを選べるようにコードを追加したいのですが、
どのようにすればいいのでしょうか?
0764名無しさん@お腹いっぱい。
2007/01/25(木) 13:56:32gdm でも使ったら?
0765名無しさん@お腹いっぱい。
2007/01/25(木) 14:01:490766名無しさん@お腹いっぱい。
2007/01/25(木) 14:05:12何がおすすめ?
0767名無しさん@お腹いっぱい。
2007/01/25(木) 14:07:200768名無しさん@お腹いっぱい。
2007/01/25(木) 14:12:47その理由は?
0769名無しさん@お腹いっぱい。
2007/01/25(木) 14:14:240770名無しさん@お腹いっぱい。
2007/01/25(木) 14:15:47wm 選べたっけ。
0771名無しさん@お腹いっぱい。
2007/01/25(木) 14:22:09xmessage のような物でも使って問い合わせるとかかな
0772名無しさん@お腹いっぱい。
2007/01/25(木) 14:26:51xdialog
0773名無しさん@お腹いっぱい。
2007/01/26(金) 01:27:22俺は$WMで分岐してる
case ${WM:-wmaker} in
wmaker) ... ;;
gnome) ... ;;
kde) ... ;;
*) ... ;;
esac
0774名無しさん@お腹いっぱい。
2007/01/26(金) 09:03:200775名無しさん@お腹いっぱい。
2007/01/26(金) 13:49:370776名無しさん@お腹いっぱい。
2007/01/26(金) 13:59:340777名無しさん@お腹いっぱい。
2007/01/26(金) 14:00:160778名無しさん@お腹いっぱい。
2007/01/26(金) 14:06:56その理由は?
0779名無しさん@お腹いっぱい。
2007/01/26(金) 14:11:340780名無しさん@お腹いっぱい。
2007/01/26(金) 17:33:130781名無しさん@お腹いっぱい。
2007/01/26(金) 17:38:480782名無しさん@お腹いっぱい。
2007/01/28(日) 05:14:10の中で、「20以上である」という条件を満たしたものが
いくつあるのかを数えたいです。
例えば、変数$listの中身が
10.4
30.2
15.4
5.2
20.2
だった場合には、答えは2と出るようにしたいのです。
n=1
sum=0
while [ $n -le 5 ]
do
s=`echo "$list" | sed -n "$n p"`
y=`trunc("$s")`
if test "$y" -ge 20
then sum=`echo "scale=0; $sum + 1" | bc`
else
exit 1
fi
n=`expr $n + 1`
done
echo $sum
0783782
2007/01/28(日) 05:15:34エラーになります。
変数$sに数値がひとつひとつ代入されて行くのは確認できたのですが、
小数点を切り捨てるためのtruncコマンドのところでエラーになります。
command substitution: line 1: syntax error near unexpected token `"$s"'
command substitution: line 1: `trunc("$s")'
どこがおかしいのか教えていただけませんか?
0784名無しさん@お腹いっぱい。
2007/01/28(日) 06:18:110785名無しさん@お腹いっぱい。
2007/01/28(日) 06:47:50というか、小数扱うなら awk 使っとけ
0786名無しさん@お腹いっぱい。
2007/01/28(日) 09:00:04nn=0; for aa in $list; do if [ ${aa%.*} -ge 20 ]; then nn=$((nn + 1)); fi; done; echo $nn;
0787名無しさん@お腹いっぱい。
2007/01/28(日) 09:14:300788782
2007/01/28(日) 09:15:01>>785
man truncしたらこんなのが出てきましたが。
つまり、truncはたぶんtrunc(数字)とかいう形で使うのかな、
と思ったのです。実際trunc "数字"ではうまくいきませんでした。
しかし、trunc()の形にしたところで
$ trunc(23.4)
-bash: syntax error near unexpected token `23.4'
こんな感じでエラーになり、たぶん正しい文法になっていないのが
ネックになっているような雰囲気です。
NAME
trunc -- truncate to integer value
SYNOPSIS
#include <math.h>
double
trunc(double x);
long double
truncl(long double x);
float
truncf(float x);
DESCRIPTION
The trunc() functions return the integral value nearest to but no larger
in magnitude than x.
SPECIAL VALUES
trunc(+-0) returns +-0.
trunc(+-infinity) returns +-infinity.
SEE ALSO
ceil(3), rint(3), math(3)
STANDARDS
The trunc() functions conform to ISO/IEC 9899:1999(E).
BSD January 29, 2003 BSD
0789782
2007/01/28(日) 09:19:35ありがとうございます。
これはなんの言語でしょうか。これがawk?
実際にこれでやってみましたがうまくいきません。
そもそも
${aa%.*}
この意味がわかりません。
けど、これを使うとtruncを使わずに済むので
便利そうですね。
いろいろと勉強してみます。
>>787
今はたまたまbashの勉強をしているので、
別にbashに依存しているわけではありません。
excelとか使った方が速いのはわかってますが、
無理やりbashでやろうとすることで
「 ( ・∀・)つ〃∩ ヘェーヘェーヘェー truncなんて関数があるんだ!」
という発見があるので、おもしろいのですよw
0790名無しさん@お腹いっぱい。
2007/01/28(日) 09:30:330791名無しさん@お腹いっぱい。
2007/01/28(日) 10:23:58それ、マニュアルページの一番上に trunc(3) て書いてるんじゃない?
マニュアルのセクション3は、Cのライブラリ関数。
0792782
2007/01/28(日) 17:54:08!!!!
全くその通りです!
bashでは使えないのですね・・・orz
bashの中でCのライブラリ関数を使う方法か、
他に小数点切り捨てによい方法はありませんか?
0793名無しさん@お腹いっぱい。
2007/01/28(日) 22:07:050794名無しさん@お腹いっぱい。
2007/01/28(日) 22:17:42[ は切り捨てないと使えないyo
0795名無しさん@お腹いっぱい。
2007/01/28(日) 22:32:23本当にbash使ってるなら、>>786 で合ってるよ。awkは関係ない。
これ自体がbashのスクリプト。
bashじゃない普通の shでも動くように >>786 を書き直してみた。
↓ (ちなみに俺は >>786 とは別人)
nn=0
for aa in $list
do
if [ `expr $aa : '\(.*\)\..*'` -ge 20 ]; then
nn=`expr $nn + 1`
fi
done
echo $nn
0796名無しさん@お腹いっぱい。
2007/01/28(日) 22:34:340797名無しさん@お腹いっぱい。
2007/01/29(月) 14:38:20ttp://x68000.q-e-d.net/~68user/unix/pickup?iconv
> 入力ファイルに無効な文字 (-f で指定した文字コードと矛盾するようなデータ) が
> 含まれていた場合、iconv はエラーとして終了する。FreeBSD の iconv では
> -c オプションを指定することで、無効な文字を無視して無視して続行することができる。
> 他の iconv では必ずエラーで終了してしまうようだ。
Linux で、変な文字を無視しつつ文字コードの変換をしたいときにはどうするのがベストでしょうか。
(個人的に馴染のある言語の) php で iconv//IGNORE をする、という手は思いついたのですが。
0798名無しさん@お腹いっぱい。
2007/01/29(月) 14:50:35Linuxでどうするのかを聞くなら
Linux板がいいでしょう。
0799782
2007/01/29(月) 21:06:29か、神!!!!
おかげさまでついにできました!
実はやりたかったことは、
「猛暑日(最高気温が35度以上の日)が2006年8月に何日あったか」
を各都市ごとに数えてみたかったのです。
そうすれば、熊本、佐賀、京都がいかに暑いところか
理解してもらえるかなと思って。
こんな感じでできました!!
ttp://sheel.mydns.jp/~sheel/moushobilastaugust.shtml
bashスクリプトファイルはここに置いておきますのね。
ttp://sheel.mydns.jp/~sheel/moushobilastaugust.sh
またいろいろと教えてください。by 皮先くん
0800782
2007/01/29(月) 21:09:19ちなみにshtmlの方は、12個の都市について
その場で気象庁からデータをとりにいって解析するので
クリックしてから表示されるまで1分弱ほど時間がかかりますので
辛抱強くお待ちくださいね。
0801名無しさん@お腹いっぱい。
2007/01/30(火) 09:09:26なかなかおもしろいね。
色々応用が利きそう。
0802名無しさん@お腹いっぱい。
2007/01/31(水) 09:39:22まだやってたんだね。
Mac板でのやりとりがなつかしいぜ…
0803782
2007/01/31(水) 16:57:2413の都市について気象庁から一気にデータを取得して
自動計算するシェルスクリプトもつくってみました。
<13の都市とは>
東京、大阪、京都、静岡、浜松、
熊本、鹿児島、枕崎、福岡、佐賀、大分、宮崎、長崎
「冬日が何日あったかを計算して表示する」
(13の都市のデータを取得するため1分弱ほど時間がかかります)
ttp://sheel.mydns.jp/~sheel/fuyubi200701.shtml
ソースはこちらです。
ttp://sheel.mydns.jp/~sheel/fuyubi200701.sh
0804名無しさん@お腹いっぱい。
2007/02/01(木) 12:23:44オレも気付いた
のでスルーしといた
0805名無しさん@お腹いっぱい。
2007/02/01(木) 14:41:450806名無しさん@お腹いっぱい。
2007/02/01(木) 21:39:01俺も気がついた
ので教えてやった。
皮先のスクリプトはよく利用させてもらってて重宝してるし。
0807名無しさん@お腹いっぱい。
2007/02/02(金) 20:25:38remsh $リモホ名 -n "find $ディレクトリ名 -type d -name $ディレクトリ名 -print"
で値が取得できるかどうかでディレクトリがあるかチェックしようと思っているのですが
もうちょっとスマートなやりかたがありますでしょうか?・・
0808名無しさん@お腹いっぱい。
2007/02/02(金) 20:30:160809名無しさん@お腹いっぱい。
2007/02/03(土) 16:34:40花子 83
裕子 98
尚美 91
という生徒のテストの点数を記載したデータがあったとき、
これを点数の高い順番でソートしたいのですが、
いろいろ調べるとawkがこういうのを得意にしているような気がしました。
この処理を簡単に行うにはawkが最も適していますか?
他に適している言語はありますか?
といいますのも、awkについて調べてみたのですが、
点数を加算する、とかはわかったのですが
点数の高い順番でソート、は無理なような気がしましたので・・・。
awkが最も適している、ということであればもうちょっとがんばってみたいと思いますが。
0810名無しさん@お腹いっぱい。
2007/02/03(土) 16:53:29ソートはsortでいいじゃん。
キーとするフィールド位置の指定だとか、アルファベット順じゃなく数の大小でのソートだとか、
そういうオプションもあるので、後はsortのmanみてみるとよいです。
0811名無しさん@お腹いっぱい。
2007/02/03(土) 16:54:590812809
2007/02/03(土) 18:17:50>>811
sort!!!!!
そ、そんな普段から自分でもよく使ってるやつで可能だったんですね!
さっそく>>811さんのようにやってみたらうまくいきました!
ありがとうございました。
0813名無しさん@お腹いっぱい。
2007/02/03(土) 18:31:44>>out.txt
を使ってどんどんファイルに書き加えていくのはわかりました。
では、ファイルに出力するのではなく、
(変数として?)メモリ上に出力していく方法はありますか?
例えば、
1回目の繰り返し文によって、変数$ssの値が5になりました。
変数$yyの中身は
5
となりました。
2回目の繰り返し文によって、変数$ssの値が2になったので、
変数$yyの中身は
5
2
となりました。
3回目の繰り返し文によって、変数$ssの値が7になったので
変数$yyの中身は
5
2
7
となりました。
こんな$ssに対して$yyのように出力が可能な方法はありますか?
0814名無しさん@お腹いっぱい。
2007/02/03(土) 18:39:33# ...
yy="$yy
$sss"
# ...
done
echo "$yy"
単純にこうやるとyyの中身の1行目に空の行が出来ちゃうから、
yyが空かどうかチェックしたほうがいいか。
0815名無しさん@お腹いっぱい。
2007/02/03(土) 18:48:28while ...; do
set "$@" "$yy"
done
for a in "$@";do
echo "$a"
done
■ このスレッドは過去ログ倉庫に格納されています