シェルスクリプト総合 その9
■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。
2007/08/15(水) 07:25:02スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>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 でトレースしましょう。
前スレ
シェルスクリプト総合 その8
http://pc11.2ch.net/test/read.cgi/unix/1171517324/
0690名無しさん@お腹いっぱい。
2007/12/30(日) 12:12:19[[ -z "$EMACS" ]] でよかろう。
0691名無しさん@お腹いっぱい。
2007/12/30(日) 18:26:58bash依存じゃない。POSIX準拠だ。
0692682
2007/12/30(日) 22:03:40皆様ありがとうございました。
仕事の環境がtcshを使うので>>1は読んでいましたが質問させていただきました。
また、対話形式でもなく(対話でもいいのですが)、スクリプトで実行したかったんです。
初心者の為、頂いた回答でも分らない部分がありますが、
年明け会社で試してみます。
ありがとうございました。
0693名無しさん@お腹いっぱい。
2007/12/30(日) 23:18:24簡単な使い方の例を挙げると、
% foreach i ( * )
と入力すると、ループ中を示すプロンプトが出てくるので、
foreach? (ここで変数$iを使った文)
foreach? :
foreach? end
みたいに実施する。
例えば拡張子が.logなファイルがある場所で、
% foreach i ( *.log )
foreach? echo "ファイル名 $i 、行数=`wc -l $i`"
foreach? echo "--- 先頭10行 ---"
foreach? head $i
foreach? echo "--- 末尾10行 ---"
foreach? tail $i
foreach? end
こんなことするときに便利なりよ。
0694名無しさん@お腹いっぱい。
2007/12/31(月) 00:21:27bashみたいに foreach i ( * ) ; do echo $i; end # do は要らないんだろうけど
みたいには使えないの?
強制的に対話モードになってしまうのが嫌なの。
0695名無しさん@お腹いっぱい。
2007/12/31(月) 16:44:41それだと、$EMACS が空文字列の場合にも
未定義と判断されてしまう。
>>681 は、空文字列の場合でも、定義済みかどうかをちゃんと判断できる。
0696名無しさん@お腹いっぱい。
2008/01/04(金) 00:49:17& が一致した箇所に置換されます
これを変数の中で bbb=\& とエスケープしないでそのまま置換させたいのですが
いい方法はないでしょうか?
またはsedじゃなくても正規表現を無視して置換するコマンドってあります?
0697名無しさん@お腹いっぱい。
2008/01/04(金) 18:00:48やりたいことは1.5GBもあるファイルをgzipを使って圧縮したいのですが、
レンタルサーバーのため負荷が高いせいか途中でkillされてしまい、
圧縮が最後まで出来ません。何か解決策をご教授いただけないのでしょうか?
宜しくお願いします。
gzip fileName
0698名無しさん@お腹いっぱい。
2008/01/04(金) 18:10:12分割して圧縮?
0699名無しさん@お腹いっぱい。
2008/01/04(金) 18:55:23レンタル鯖のルールがよくわからんが、ファイルの大小に関係なくファイル圧縮の
CPU使用率なんてタカが知れているから、おそらくCPU時間を測っていて、タイムアウト的に
討ち取られていると思う(CPU負荷は小さいがCPU時間は長くなる)
というわけで>>698の言う通り、splitして分割圧縮するしかないな。
0700名無しさん@お腹いっぱい。
2008/01/04(金) 19:09:510701名無しさん@お腹いっぱい。
2008/01/04(金) 19:37:54僕のPCのシェルはXtermというものみたいです。
これは、シェル系に当てはめると何シェル系なんでしょうか?
0702名無しさん@お腹いっぱい。
2008/01/04(金) 19:39:360703江戸っ子
2008/01/04(金) 21:34:590704名無しさん@お腹いっぱい。
2008/01/04(金) 23:11:46マジレスするとxtermはshellじゃない。
0705名無しさん@お腹いっぱい。
2008/01/05(土) 00:18:57僕のPCのシェルはTeraTermというものみたいです。
これは、シェル系に当てはめると何シェル系なんでしょうか?
0707名無しさん@お腹いっぱい。
2008/01/05(土) 01:31:180708名無しさん@お腹いっぱい。
2008/01/05(土) 08:59:59ddで先頭から順に適当な長さずつ切り出しながら | gzip -c >> file.gz に繋ぐ。
dd if=file bs=適当 skip=0 count=1 | gzip -c > file.gz
dd if=file bs=適当 skip=1 count=1 | gzip -c >> file.gz
dd if=file bs=適当 skip=2 count=1 | gzip -c >> file.gz
...
0709名無しさん@お腹いっぱい。
2008/01/05(土) 09:05:05せんせー、ktermは?
0710名無しさん@お腹いっぱい。
2008/01/05(土) 09:54:280711名無しさん@お腹いっぱい。
2008/01/05(土) 10:16:01ひねりが足りない。
0712名無しさん@お腹いっぱい。
2008/01/05(土) 10:42:030713名無しさん@お腹いっぱい。
2008/01/05(土) 17:02:33n=2 の時は
command "$1" "$2"
n=4 の時は
command "$1" "$2" "$3" "$4"
というように、変数nに応じて引数の数を変える処理をしたいと思ってます。
command "$1" ... "$n"
どうすれば実現できるでしょうか?
0714名無しさん@お腹いっぱい。
2008/01/05(土) 17:13:030715名無しさん@お腹いっぱい。
2008/01/05(土) 17:13:270716名無しさん@お腹いっぱい。
2008/01/05(土) 17:20:44'があるため展開されずに困っているのですが、
どうすればいいでしょうか?
----------------------------------------
hensu=123
command arg='${hensu}'
----------------------------------------
0717名無しさん@お腹いっぱい。
2008/01/05(土) 18:11:44それ、gzファイルが切れ目なくくっついちゃって、解凍できなくないか?
0718名無しさん@お腹いっぱい。
2008/01/05(土) 18:17:37'を使わない。
0719名無しさん@お腹いっぱい。
2008/01/05(土) 18:34:06知らないなら試せよ。
0720名無しさん@お腹いっぱい。
2008/01/05(土) 19:42:03レスありがとうございます。
いや、'を使わないとcommandの処理が正常に終了したいので、
どうにかして'付きで渡したいんです。宜しくお願いします。
0721名無しさん@お腹いっぱい。
2008/01/05(土) 19:57:50'で囲まれるとパラメーター置換は行われない。'で囲む事とパラメーター置換を行う事は排他。
0722名無しさん@お腹いっぱい。
2008/01/05(土) 20:11:42教えていただいて、ありがとうございます。難しいですね。
そうしたら、例えば、phpでいうと、
"'" . $hensu . "'"
のような文字列を結合することってできますか?
0723名無しさん@お腹いっぱい。
2008/01/05(土) 20:11:440724名無しさん@お腹いっぱい。
2008/01/05(土) 20:12:36$hensu を展開した上で、commandには ' ' を付けて渡したいということだろ?
だったら、
command arg=\'$hensu\'
>>721
知らないなら黙ってればいいのに。
0725名無しさん@お腹いっぱい。
2008/01/05(土) 20:19:31初めて知った
gzipはパイプ前段でddが動いてることも、>>でシェルが同じファイルに追加書きしてることも
わからないと思うんだけど、どうやって同じファイルを分割圧縮してるんだ?
0726名無しさん@お腹いっぱい。
2008/01/05(土) 20:43:53ハイハイ>>722見て後出し。>>721の何処が正しくないんだ言ってみろクズ。
0727名無しさん@お腹いっぱい。
2008/01/05(土) 20:50:33' ' で囲んだ上でパラメータ置換を行なうことはできる。排他ではない。
0728名無しさん@お腹いっぱい。
2008/01/05(土) 21:08:09クォートで渡すとhensuに空白文字があったときに面倒なことになる気がす
0729名無しさん@お腹いっぱい。
2008/01/05(土) 21:34:54>>724は囲んでいるのではなく、'を連結しているだけ。 しかも>>728が指摘しているとおり無様。
>>728は一見囲んでいるようには見えるが、arg="'${hensu}''"でも通るので却下。
0730名無しさん@お腹いっぱい。
2008/01/05(土) 21:37:28>>728は>>722の回答としては正しい。
> 'で囲まれるとパラメーター置換は行われない。
の反例としては却下。
0731名無しさん@お腹いっぱい。
2008/01/05(土) 21:42:10dd if=file bs=適当 skip=0 count=1 | gzip -c > 1.gz
dd if=file bs=適当 skip=1 count=1 | gzip -c > 2.gz
dd if=file bs=適当 skip=2 count=1 | gzip -c > 3.gz
cat ?.gz > file.gz
とやったfile.gzでも、gzip -dで全体が解凍できたわ。一方gzipをcompress/uncompressに
変えたら、ファイル蛾物故割れて解凍できなかった。圧縮時は単なるファイルの連結でも、
解凍時にgzipが連結ファイルであることを認識して、続きを解凍してくれてるんだな。
0732名無しさん@お腹いっぱい。
2008/01/05(土) 23:03:18>の反例としては却下。
却下
0733名無しさん@お腹いっぱい。
2008/01/05(土) 23:57:08↓これへの反論も出来ない池沼は黙ってればいいのに。
>>728は一見囲んでいるようには見えるが、arg="'${hensu}''"でも通るので却下。
0734名無しさん@お腹いっぱい。
2008/01/06(日) 00:07:54それがどうした。
却下
0735名無しさん@お腹いっぱい。
2008/01/06(日) 12:52:56du -sh 以外で高速な方法はないでしょうか。
ファイル数や容量が多い場合、
du -sh にかなり時間がかかることが多いためです。
0736名無しさん@お腹いっぱい。
2008/01/06(日) 20:28:38それらファイルの所有者を測定用ユーザにしてquotaを設定しとく
0737名無しさん@お腹いっぱい。
2008/01/07(月) 02:33:08n=1
var${n}=foo
echo var1=foo
直接はできないっぽいんですが、こういう時の上手い手ってありますか?
0738名無しさん@お腹いっぱい。
2008/01/07(月) 02:59:13eval var$n=foo
0740名無しさん@お腹いっぱい。
2008/01/08(火) 16:30:29shスクリプトの中で、readで読んだ変数に改行コードらしきコードが入っていて、
うまく処理が動きません。
シェル変数 AAA,BBBの最後の1バイトを取ってあげれば動くと思うんですが、
どうやれば良いでしょうか?
以下がサンプルのスクリプトです。
コマンドラインで起動すると、PATH_VARは、キーボードから入力した2つの文字列が
'/'で連結されて表示されるのですが、これをinetd経由でtelnetから起動すると、
PATH_VARが変な文字(シェル変数AAAが設定されない?)となってしまいます。
#!/bin/sh
read AAA
read BBB
PATH_VAR="$AAA/$BBB"
echo $PATH_VAR
0741名無しさん@お腹いっぱい。
2008/01/08(火) 16:38:40readで読み込むと、改行コードは自動的に取り除かれる。
問題になってるのは、改行 \n じゃなくて 復帰 \r (^M) じゃないのかな
^M を取り除くには tr とか使う。
0742名無しさん@お腹いっぱい。
2008/01/08(火) 16:44:33read AAA
read BBB
PATH_VAR=`echo "$AAA/$BBB" | tr -d '\015'`
echo $PATH_VAR
0743名無しさん@お腹いっぱい。
2008/01/08(火) 16:59:36THXです。
おっしゃる通り、改行ではなく復帰でした。
だから、PATH_VARを表示した時に、AAAが表示されなかったんですね。
大変助かりました、どうもありがとうございました。
改修バージョンはこんな感じになりました。
#!/bin/sh
read line ; AAA=`echo $line | tr -d \\\r`
read line ; BBB=`echo $line | tr -d \\\r`
PATH_VAR="$AAA/$BBB"
echo $PATH_VAR
0744名無しさん@お腹いっぱい。
2008/01/08(火) 17:48:070745名無しさん@お腹いっぱい。
2008/01/08(火) 19:03:22そういうやり方もありですね。
>>745
echo $AAA | hd
ってやるとちゃんと制御コードが確認出来ました。
シェル変数の中身ってこうすればHEXでみれたんですね。
\とか、"とか、'とか、`とかをシェル変数に突っ込むときに、
いつも困ってたんですが、良いこと聞きました。
ありがとう。
0746名無しさん@お腹いっぱい。
2008/01/09(水) 13:39:560747名無しさん@お腹いっぱい。
2008/01/09(水) 13:45:28よりポータブルには、od -Ax -t x1 だな。
0748名無しさん@お腹いっぱい。
2008/01/17(木) 00:04:480749名無しさん@お腹いっぱい。
2008/01/17(木) 00:23:08read v1 v2 v3
0750名無しさん@お腹いっぱい。
2008/01/17(木) 01:03:42read -d ,
0751名無しさん@お腹いっぱい。
2008/01/17(木) 03:52:18find . -type f -regex ".*\.[ch]\(pp\|xx\)?"
で*.cppとか.hだけを列挙できるわけですが
updatedbの--findoptionsに
updatedb --findoptions='-type f -regex ".*\.[ch]\(pp\|xx\)?"' --localpath='./' --output='/home/someone/sources.db'
などと同様に指定してもうまくフィルタリングされません(上のコマンドで生成されたものを使うと普通にディレクトリ名や要らないファイルが引っかかる)
どうにかupdatedbで生成されるデータベースの内容をコントロールする手は無いんでしょうか?
0752名無しさん@お腹いっぱい。
2008/01/18(金) 00:42:15そんなオプションがあるんだ。
プラットフォームは何?
クォートに問題がある気がするんだけど、これならどう?
--findoptions="-type f -regex \".*\.[ch]\(pp\|xx\)?\""
0753名無しさん@お腹いっぱい。
2008/01/18(金) 22:20:53OSによって違うだろうけど道具はあるはず。
多少牛刀な気もするがシステムコールのトレースとか。
0754名無しさん@お腹いっぱい。
2008/01/19(土) 00:57:26おっぱいが牛みたいな可愛い女の子剣士?
0755名無しさん@お腹いっぱい。
2008/01/19(土) 02:36:191. 「牛をぶった切るための刀」
2. 「牛刀をもって鶏を割く」の略
3. 「おっぱいが牛みたいな可愛い女の子剣士」
好きなの選べ
0756名無しさん@お腹いっぱい。
2008/01/19(土) 02:55:18OSによって違うだろうけど道具はあるはず。
多少おっぱいが牛みたいな可愛い女の子剣士な気もするがシステムコールのトレースとか。
0757名無しさん@お腹いっぱい。
2008/01/19(土) 10:17:30実装によるが、updatedbからのfindの呼び出しが、絶対PATHじゃないなら、
findの偽物スクリプトを作って、PATHを先に通して
引数を表示させれば良い。
#!/bin/sh
echo "$@"
みたいな。
絶対PATHの場合はちょっと厄介だが、
/usr/bin/findを一時的にリネームして、偽物findスクリプトに置き換える。
0758名無しさん@お腹いっぱい。
2008/01/19(土) 10:51:510759名無しさん@お腹いっぱい。
2008/01/19(土) 10:53:30>絶対PATHの場合はちょっと厄介だが、
>/usr/bin/findを一時的にリネームして、偽物findスクリプトに置き換える。
客先でそれやった馬鹿がいた。しかも本番環境で……
cronで動いていた業務処理が止まり、大騒ぎに。
0760名無しさん@お腹いっぱい。
2008/01/19(土) 11:01:09#!/bin/sh
echo $@
find $@
0761名無しさん@お腹いっぱい。
2008/01/19(土) 11:12:19そ〜ゆ〜のは、テスト環境でやるもの。
0762名無しさん@お腹いっぱい。
2008/01/19(土) 11:18:480763名無しさん@お腹いっぱい。
2008/01/19(土) 12:02:32それ、スクリプト無限ループw 釣りか?
あと、$@ は "$@" にしないと $@ の意味をなさない。
0764名無しさん@お腹いっぱい。
2008/01/19(土) 12:30:000765名無しさん@お腹いっぱい。
2008/01/19(土) 13:17:500766名無しさん@お腹いっぱい。
2008/01/19(土) 13:26:50思いもよらなかった。
execをすり替えてロギングするライブラリ作ってLD_PRELOADあたりを
想定していたんだが。
0767名無しさん@お腹いっぱい。
2008/01/19(土) 13:40:24LD_PRELOAD だと、コンパイルが必要。
シェルスクリプトでできるものはシェルスクリプトで済ませる方がエレガント。
まさかとは思うが、>>766 は wrapper scriptの類を、
いちいちexecv() とかで書いてコンパイルしてるのかな?
0768名無しさん@お腹いっぱい。
2008/01/19(土) 13:50:17つか, あるもん使えばいいんじゃね?
0769名無しさん@お腹いっぱい。
2008/01/19(土) 13:52:31それと、「コンパイル不要」とがどう結び付くんだよ。
あと、FreeBSD限定の話をされてもな
0770名無しさん@お腹いっぱい。
2008/01/19(土) 14:40:32そんな面倒な事しなくても DTrace 使えば良いじゃない
0771名無しさん@お腹いっぱい。
2008/01/19(土) 17:16:190772名無しさん@お腹いっぱい。
2008/01/19(土) 17:28:10>>759
> 客先でそれやった馬鹿がいた。しかも本番環境で……
0773名無しさん@お腹いっぱい。
2008/01/19(土) 17:39:20それこそおっぱいが牛みたいな可愛い女の子剣士だろ
0774名無しさん@お腹いっぱい。
2008/01/19(土) 17:47:030775名無しさん@お腹いっぱい。
2008/01/19(土) 23:12:58Cron+Cシェルで
http://www.hoge.com/hoge.php
を実行するのを書かなきゃいけなくなってしまいました。
1:同一サーバー内の、hoge.phpを実行するにはなんて書けばいいでしょうか?
SHELL=/bin/csh
** Cronの設定 **
/home/*****/www.hoge.com/hoge.php
2:外部のサーバー(これもCシェル)からからの場合は、http〜と直接書けるのでしょうか?
SHELL=/bin/csh
** Cronの設定 **
http://www.hoge.com/hoge.php #OK?
0776名無しさん@お腹いっぱい。
2008/01/19(土) 23:42:580777名無しさん@お腹いっぱい。
2008/01/19(土) 23:49:020778名無しさん@お腹いっぱい。
2008/01/19(土) 23:52:420779名無しさん@お腹いっぱい。
2008/01/19(土) 23:53:080781775
2008/01/20(日) 01:03:14解決しました。 wgetのそういう使い方もあるんですね。
Cshなのは、鯖屋さんの関係です。
0782名無しさん@お腹いっぱい。
2008/01/25(金) 22:42:49使えそうなのはawkくらいだが、こいつは秒が変わる前に二度呼ぶと
同じ値を返してしまう。
awk 'BEGIN{srand();print rand()}'
$RANDOMはbash依存。jotはBSD系。/dev/randomもあるかどうかわからん。
perl -e 'print rand()'が一番ましだろうか。
0783名無しさん@お腹いっぱい。
2008/01/25(金) 22:50:06exprで乱数計算。
0784名無しさん@お腹いっぱい。
2008/01/26(土) 00:42:39dateのmanを見ていたら、
%N nanoseconds (000000000..999999999)
というのがあった。こんな感じ
% echo -n `date +%N`
431218994 % echo -n `date +%N`
857494685 % echo -n `date +%N`
269031777 % echo -n `date +%N`
803351248 % echo -n `date +%N`
195538275 % echo -n `date +%N`
538357509 % echo -n `date +%N`
058776188 %
453 名前:login:Penguin[sage] 投稿日:2008/01/16(水) 23:09:59 ID:PJonPFmQ
jotはたぶんBSD系限定だよな。
jot -r 10 1 6
/dev/urandomは10進数テキストで得るのがめんどーだろうか。
dd if=/dev/urandom bs=2 count=1 2>/dev/null | od -vd
左カラムがじゃまだな。 sed 1q |cut -f2 -d' ' とかで削るか。
454 名前:login:Penguin[sage] 投稿日:2008/01/16(水) 23:21:36 ID:KAlEWwYc
>452,453 なるほど.date +%Nはいい感じ.
jot便利そうだよ,jot.犬にもこんなの欲しいな.
ありがとう
455 名前:login:Penguin[sage] 投稿日:2008/01/16(水) 23:24:18 ID:HQvmxN1E
od -t u1 /dev/urandom | awk '{print $2;exit}'
0785名無しさん@お腹いっぱい。
2008/01/26(土) 09:53:030786名無しさん@お腹いっぱい。
2008/01/26(土) 10:44:55でどうよ。
余計なrand()一発は、FreeBSDの実装で、srand直後のrandがおかしいため。
+%sもない前時代までポータブルにしないといかんか?
0787名無しさん@お腹いっぱい。
2008/01/26(土) 11:19:04じゃあ、date +%s がない Solaris10 は前時代のOSなんだw
0788名無しさん@お腹いっぱい。
2008/01/26(土) 12:24:46シーラカンスだろ
0789名無しさん@お腹いっぱい。
2008/01/26(土) 14:52:38■ このスレッドは過去ログ倉庫に格納されています