シェルスクリプト総合 その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 でトレースしましょう。
0698名無しさん@お腹いっぱい。
2007/01/01(月) 01:30:450699名無しさん@お腹いっぱい。
2007/01/01(月) 02:23:40Yellow Mookだろ。
それくらい察してやってくれ。
0700名無しさん@お腹いっぱい。
2007/01/02(火) 11:18:36素で分からんかったorz
0701名無しさん@お腹いっぱい。
2007/01/03(水) 19:21:380702名無しさん@お腹いっぱい。
2007/01/03(水) 19:36:330703名無しさん@お腹いっぱい。
2007/01/09(火) 22:08:180704名無しさん@お腹いっぱい。
2007/01/10(水) 15:53:220705名無しさん@お腹いっぱい。
2007/01/10(水) 15:59:180706名無しさん@お腹いっぱい。
2007/01/11(木) 20:32:03失礼しました
0707名無しさん@お腹いっぱい。
2007/01/11(木) 22:03:310708名無しさん@お腹いっぱい。
2007/01/12(金) 00:58:20sed 's/aaa/bbb/' hoge.dat > tmp.dat
mv tmp.dat hoge.dat
のようにして、一時的なファイルとしてtmp.datというファイルを用意するのが無駄だと
思うのですが、このような一時的なファイルを使わないで
直接、hoge.datをsedで編集する方法はありませんでしょうか?
m(_ _)m
0709名無しさん@お腹いっぱい。
2007/01/12(金) 01:08:30・-i オプションをつかう
・-i オプションがないsedをつかっているなら in-place editing 対応の sed の導入を検討する
・ed をつかう
・perl を使う
・一時ファイルを必要としないファイル命名法を検討する
お好みで
0710名無しさん@お腹いっぱい。
2007/01/12(金) 01:10:26あとinplaceというあらゆるフィルタをin-place editに使うコマンド
もある。(これはぐぐって)
0711名無しさん@お腹いっぱい。
2007/01/12(金) 01:20:43NetBSD の標準 sed には -i オプションは無い。
OpenBSDの(ry
以前のGNU sed には in-place editing 機能はない (Changelog によると 2001-09-25 )
0712名無しさん@お腹いっぱい。
2007/01/12(金) 01:29:180713名無しさん@お腹いっぱい。
2007/01/12(金) 01:33:43http://www.idaemons.org/projects/inplace/
へー、これか。
これは知らなかった。
0714名無しさん@お腹いっぱい。
2007/01/12(金) 01:35:17MacOSXのFreeBSDなユーザーランドは 最初は FreeBSD 3.xR由来で
そのうちに 5.x由来とかのになってそれから先はシラネ。
でも5.x以降だろうなと推測。
0715名無しさん@お腹いっぱい。
2007/01/12(金) 01:45:52/usr/share/misc/bsd-family-tree あたりにちゃっかり書いてあったりする。
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板がいいでしょう。
■ このスレッドは過去ログ倉庫に格納されています