シェルスクリプト総合 その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/
0102名無しさん@お腹いっぱい。
2007/09/13(木) 18:19:13while :; do :; done
とかは?
0103名無しさん@お腹いっぱい。
2007/09/13(木) 18:21:52whileで無限ループはかけてますよ。
0104名無しさん@お腹いっぱい。
2007/09/13(木) 18:33:29単にシェルのなかでビジーループするだけのほうがCPU占有するだろうと
思えるから書いたんだが。
0105名無しさん@お腹いっぱい。
2007/09/13(木) 18:44:01>>103 みたいな、恩を仇で返すような質問者にはなりたくないなぁ
0106名無しさん@お腹いっぱい。
2007/09/13(木) 19:03:590107名無しさん@お腹いっぱい。
2007/09/13(木) 19:06:19実験注意
0108名無しさん@お腹いっぱい。
2007/09/13(木) 19:13:45ようこそ、バーボンハウスへ。
このしょっぱいロールケーキはサービスだから、まず食べて落ち着いて欲しい。
実は、君に一生セクロス出来ない呪いをかけたんだ。
うん、「また」なんだ。済まない。
仏の顔もって言うしね、謝って許してもらおうとも思っていない。
↓このスレに「こんばんは、プッシーキャットです」とレスすれば呪いは解ける。
http://ex21.2ch.net/test/read.cgi/voiceactor/1189073996/
じゃあ、注文を聞こうか。
0110名無しさん@お腹いっぱい。
2007/09/13(木) 20:02:20どうでもいいが、君は>>101かな?
レス番ずれとるぞ
0111名無しさん@お腹いっぱい。
2007/09/13(木) 23:40:34それのどこがファイル表示してんだ?wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww
ばかばっかりwwwwwww
0112名無しさん@お腹いっぱい。
2007/09/14(金) 00:12:41( ・ω・)んも〜
○={=}〇,
|:::::::::\, ', ´
、、、、し 、、、(((.@)wwwwwwwwwww
0113名無しさん@お腹いっぱい。
2007/09/14(金) 00:36:44>>94は「行頭行末の空白が出ない」って言いたいんだろ。 >>60 参照。
0114名無しさん@お腹いっぱい。
2007/09/14(金) 19:39:12ファイルからコマンドラインを読み込んでるだけですよね?
だったら、なぜシェルスクリプトのモード(?)の時は、
プロンプトが出ないんですか?
プロンプトを出す方法はありますか?
0115名無しさん@お腹いっぱい。
2007/09/14(金) 20:25:19させたいのですが、bashで乱数を発生させるのにはどうすれば
良いでしょうか?
何に使うかというと、
OSはCentOS5.0です。NFSサーバが一台、NFSクライアントが100台です。
NFSクライアントの個々のlocal HDDのファイルを土曜深夜に
自動バックアップさせようと思っていますのでcrontabに一行
書こうと思っています。1台あたりのバックアップは10秒もか
かりません。
うんで、100台が一斉にバックアップはじめるとサーバが死ぬので
ランダムにsleepを居れたいのですが、、、
100台のcrontabの時間を1分刻に変更してくなんて、めんどくさい
にょろ。
0116名無しさん@お腹いっぱい。
2007/09/14(金) 20:27:50sleep $((RANDOM*1800/32768))
0118名無しさん@お腹いっぱい。
2007/09/14(金) 20:32:040119名無しさん@お腹いっぱい。
2007/09/14(金) 21:03:49次はこっちで聞こうな。
シェルスクリプト総合@LINUX Part3
http://pc11.2ch.net/test/read.cgi/linux/1184077033/
0120名無しさん@お腹いっぱい。
2007/09/14(金) 21:25:44>ファイルからコマンドラインを読み込んでるだけ
違う。
プロンプトではコマンドラインしか実行できないが、
シェルスクリプトではコマンドラインの他、
if文とかfor文とか、変数の代入とかもできるようになる。
そもそも別物なので、プロンプトは出ない。
0121名無しさん@お腹いっぱい。
2007/09/14(金) 21:49:470122名無しさん@お腹いっぱい。
2007/09/14(金) 22:08:09$ for i in hoge
for: Command not found.
って出るし。
変数も使えない。
$ HOGE=hage
HOGE=hage: Command not found.
0123名無しさん@お腹いっぱい。
2007/09/14(金) 22:33:150124名無しさん@お腹いっぱい。
2007/09/14(金) 22:46:57シェルがプロンプトを出力するのは、ユーザに入力を受け付ける事ができるようになった事を表すため。
なので、基本的にその必要のない、非対話的(>シェルスクリプトのモード)な動作をするときはプロンプトを出力しない。
この対話的、非対話的であるということは起動時に決定され移行する手段もないためスクリプト実行中にプロンプトを出力する事は出来ない。
0125名無しさん@お腹いっぱい。
2007/09/14(金) 23:37:55set -i すればプロンプト出るよw
0127名無しさん@お腹いっぱい。
2007/09/15(土) 08:45:14これで満足か? イケヌマ君。www
echo " aaa" >file
while read line; do echo $line; done <file
0128名無しさん@お腹いっぱい。
2007/09/16(日) 21:05:08こんなどうしようもないショボい釣り針は初めて
うっかり釣られたけど、どうやったらこんなショボいこと浮かぶの?
0129名無しさん@お腹いっぱい。
2007/09/16(日) 21:08:42本当に使えないんですが,,,
使えるようになる設定とかあるんですか???
0130名無しさん@お腹いっぱい。
2007/09/16(日) 21:21:06もし使えたらおかしなことになるだろ。
例えば forだったら、doneコマンドを実行したら
doコマンドのところまで後ろにジャンプしないといけない。
コマンドラインでは、打ったコマンドを順番に実行するだけだから、
後ろに戻るような動作はできない。
forを使いたきゃ、シェルスクリプトに一旦書くしかない。
0131名無しさん@お腹いっぱい。
2007/09/16(日) 21:51:01コマンドラインでfor文を使いたければ、Cシェル系(foreach)でも使ったら?
0132名無しさん@お腹いっぱい。
2007/09/16(日) 22:02:42もしかしてマジ?そんな環境があるのか知らないけど
取り合えず以下でも受け付けない?
for x in a b; do echo $x ; done
0133名無しさん@お腹いっぱい。
2007/09/16(日) 22:09:27for: Command not found.
x: Undefined variable.
0134名無しさん@お腹いっぱい。
2007/09/16(日) 22:18:59$ csh
%set prompt='$ '
$ for x in a b; do echo $x;done
for: Command not found.
x: Undefined variable.
0135名無しさん@お腹いっぱい。
2007/09/16(日) 22:20:51まじですまないがググらんと原因が分からないんでパス
0136名無しさん@お腹いっぱい。
2007/09/16(日) 22:26:14いやプロンプトをどうするかは自由だけどね
0137名無しさん@お腹いっぱい。
2007/09/17(月) 10:19:560138名無しさん@お腹いっぱい。
2007/09/17(月) 18:50:07でも >>129-131 の時点で自演に気付けなかった自分にorz
参りました一生romってます
0139名無しさん@お腹いっぱい。
2007/09/18(火) 19:37:25非常に簡単なスクリプト、たとえば以下のような場合ですが
このままでいいのですかね?
もうちょっとスクリプトらしく書けとかありません?^^;
役割果たすならシンプルが一番なのかもしれませんが
シェルスクリプトというよりコマンドの羅列なので・・
#!/bin/sh
ls -i /var/log/syslog > var/log/check.log
date >> var/log/check.log
0140名無しさん@お腹いっぱい。
2007/09/18(火) 20:15:57var/log/check.logを、わざわざ相対PATHで書いてるのはなぜ?
これだと、このシェルスクリプトを / で実行しないと
期待通り動かないよ。
もうちょっとシェルスクリプトらしくするには、
例えば↓
#!/bin/sh
CHECK_LOG=/var/log/check.log
{ ls -i /var/log/syslog; date; } > $CHECK_LOG
0141139
2007/09/18(火) 22:35:51おぉー、シェルスクリプトになっていますね。
こういうのは慣れなのでしょうか^^;
相対パスになっていたのも気がつきませんでした。
これも慣れるんでしょうかね・・
がんばります。アドバイスどうもありがとうございました。
0142名無しさん@お腹いっぱい。
2007/09/18(火) 23:10:07#!/bin/sh
CHECK_LOG=/var/log/check.log
exec > $CHECK_LOG
ls -i /var/log/syslog
date
0143139
2007/09/19(水) 00:41:33レスありがとうございます。
なるほど、execコマンドって便利そうですね。
本で読んでみましたが最初よくわかりませんでしたw
リダイレクトの章を読んでで納得^^
こんな簡単な処理でもいろんな書き方があって
奥が深いですねヽ(´ー`)ノ
0144名無しさん@お腹いっぱい。
2007/09/19(水) 08:11:38>>142 は半分ネタだろ。真に受けるなw
execリダイレクトしてしまうと、今後この後に別のコマンドを追加した場合、
すべてリダイレクトされてしまって、保守性の悪いスクリプトになる。
0145名無しさん@お腹いっぱい。
2007/09/19(水) 08:29:17/root/test.1.txt
/root/test-1.txt
があります。
find / -regex "/root/[a-z0-9\-\.]+\.txt"
としても
/root/test-1.txt
だけ見つかりません。
\.をはずすと
なぜか
/root/test-1.txtが見つかるのですが、これはなぜでしょうか?
0146名無しさん@お腹いっぱい。
2007/09/19(水) 08:40:10正規表現の [ ] の中で、\ は意味ないわけだが。\- としてもだめ。
0147名無しさん@お腹いっぱい。
2007/09/19(水) 08:41:110148145
2007/09/19(水) 08:54:43find での正規表現の利用の
仕方が関係ある気がします。
perl互換の正規表現を使ってperlなどでは
[a-z-.]でいけるんですが、
find でこれを使うと Invalid range end が表示されてしまいます。
0149名無しさん@お腹いっぱい。
2007/09/19(水) 09:04:420150名無しさん@お腹いっぱい。
2007/09/19(水) 09:33:06find /root -regex "/root/[-.a-z0-9]+\.txt"
0151名無しさん@お腹いっぱい。
2007/09/19(水) 09:35:010152名無しさん@お腹いっぱい。
2007/09/19(水) 18:54:590153名無しさん@お腹いっぱい。
2007/09/19(水) 20:16:33見た感じfork爆弾なのかなと思ったけど、どうなんだろ。
#!/bin/sh
$0 & $0 &
でよさそーな気もする。
0154名無しさん@お腹いっぱい。
2007/09/20(木) 13:26:36この{}の意味って何なのでしょうか?
()のサブシェルとの違いは?
0155名無しさん@お腹いっぱい。
2007/09/20(木) 13:28:51意味以前に、{ } の文法間違ってる。それでは正しく動かない。
0156名無しさん@お腹いっぱい。
2007/09/20(木) 15:53:30zshなら動くみたい
>>154
cd; foo=''; { cd /tmp; foo=bar; }; pwd; echo $foo
と
cd; foo=''; (cd /tmp; foo=bar); pwd; echo $foo
を実行してみればわかるかも
0157名無しさん@お腹いっぱい。
2007/09/20(木) 16:21:490158名無しさん@お腹いっぱい。
2007/09/20(木) 17:31:38もちろん、SHELL=/bin/sh と、あらかじめ設定されてます。
#!$SHELL
echo helloworld
0159名無しさん@お腹いっぱい。
2007/09/20(木) 17:35:19( ゚д゚ )
( ゚д゚ )
0160名無しさん@お腹いっぱい。
2007/09/20(木) 17:44:060161名無しさん@お腹いっぱい。
2007/09/20(木) 17:45:310162名無しさん@お腹いっぱい。
2007/09/20(木) 18:00:590163名無しさん@お腹いっぱい。
2007/09/20(木) 20:12:04exportは既にしています
>>162
ありがとうございます。zshにしたら動きました
0164名無しさん@お腹いっぱい。
2007/09/22(土) 18:06:21ls fileA | awk '{print $5}' ってな感じで抜き出して比較しないとダメですか?
0165名無しさん@お腹いっぱい。
2007/09/22(土) 18:26:34testコマンドではファイルサイズが0かどうかの判定しかできないね。
ls | awk じゃ無駄。
wc -c を使うと良い。
if [ `wc -c < fileA` -gt `wc -c < fileB` ]; then
みたいに。
wc -cの結果にファイル名が出ずにファイルサイズの数字のみになるように、
wc -c fileA じゃなくて wc -c < fileA にするのがコツ。
0166名無しさん@お腹いっぱい。
2007/09/22(土) 18:48:12wcの-cオプションて国際化されててもバイト数を返すんだな。
-mで文字数か。
0167名無しさん@お腹いっぱい。
2007/09/23(日) 00:40:46どのへんのOSに入ってるかまでは把握してない...
0168名無しさん@お腹いっぱい。
2007/09/23(日) 03:12:27Coreutils か Shellutils じゃなかったっけ?
0169名無しさん@お腹いっぱい。
2007/09/23(日) 05:30:150170名無しさん@お腹いっぱい。
2007/09/23(日) 11:20:40stat -c %s file
で、ファイルサイズだけ表示できるが、
FreeBSDのstatはcoreutilsのではなくて、
オプションは違うし、互換性がない。
Solarisではstatはない。
0171名無しさん@お腹いっぱい。
2007/09/25(火) 10:35:27tcsh がない OS もあるけど、stat よりはマシ。
tcsh -fc 'filetest -Z filename'
0172名無しさん@お腹いっぱい。
2007/09/25(火) 10:37:40いや、tcsh使うくらいなら >>165 の wc -c < file で決まりだろ。
0173名無しさん@お腹いっぱい。
2007/09/25(火) 10:39:100174名無しさん@お腹いっぱい。
2007/09/25(火) 10:41:54wc はファイルをオープンするので read permission がないファイルでコケるし、
読めても巨大なファイルでは I/O に時間がかかる。
filetest はその問題はない。
0175名無しさん@お腹いっぱい。
2007/09/25(火) 10:45:05おいおい、本気でファイルなめると勘違いしてたのかよ。
wc -c < file ならファイルはなめないよ。
open()して、ファイルサイズ取得するだけ。
巨大なファイルでも一瞬。
0176名無しさん@お腹いっぱい。
2007/09/25(火) 10:47:150177名無しさん@お腹いっぱい。
2007/09/25(火) 10:55:45うんにゃ。実装依存なので期待しない方がいい。
俺の知ってるかぎりでは GNU の wc 以外でそれをやるものはない。
パーミッションの問題は変わらないし。
0178名無しさん@お腹いっぱい。
2007/09/25(火) 11:16:07wc -c < file だとなめるけど、
wc -c file だとなめないね。
ファイル名表示されるのが邪魔だけど、
wc -c file の方使えばいいか。
0179名無しさん@お腹いっぱい。
2007/09/25(火) 14:32:430180名無しさん@お腹いっぱい。
2007/09/25(火) 22:37:120181名無しさん@お腹いっぱい。
2007/09/26(水) 00:16:57lrwxr-xr-x 1 root wheel 7 Sep 26 00:13 $SHELL -> /bin/sh
$ cat scr
#!$SHELL
echo a
$ ./scr
a
0182名無しさん@お腹いっぱい。
2007/09/26(水) 10:18:400183名無しさん@お腹いっぱい。
2007/09/26(水) 12:20:36ファイル名が表示されたら、そもそもの [ x -gt y ] が使えないとおも
0184名無しさん@お腹いっぱい。
2007/09/26(水) 12:28:03set `wc -c fileA`
A=$1
set `wc -c fileB`
B=$1
if [ $A -gt $B ]; then
0185名無しさん@お腹いっぱい。
2007/09/26(水) 13:10:43それだったら、↓の方が簡単
set `wc -c fileA` `wc -c fileB`
if [ $1 -gt $3 ]; then
…
0186名無しさん@お腹いっぱい。
2007/09/26(水) 15:52:53>>185
このsetの使い方ってどういうことなのでしょうか?
理解すれば幅が広がりそう。
0187名無しさん@お腹いっぱい。
2007/09/26(水) 17:09:39ポジショナルパラメータをセットする
0188名無しさん@お腹いっぱい。
2007/09/27(木) 23:09:07下記のような入力データから、ワークに1行入力して、
ABCDE 12
BC 123
A
BB
CCCCC 2
変数Xへ、2番目のフィールドを取り出す場合は
どうすればよいでしょうか。
もちろん、2番目で空白の場合は、0または読み
飛ばしする。
0189名無しさん@お腹いっぱい。
2007/09/27(木) 23:24:54while read dummy x; do
echo ${x:-null}
done < file
0190名無しさん@お腹いっぱい。
2007/09/27(木) 23:32:34ありがとうございました。勉強になりました。
0191名無しさん@お腹いっぱい。
2007/09/29(土) 11:38:30NGの場合:
# A=/
# expr substr A 1 1
シンタックスエラー
このシンタックスエラーになる理由がわかりません。Linux(Plamo)ではOKみたいす。
OKの場合:
# A=/a
# expr substr A 1 1
# /
勉強不足ですいませんが、ご教示ください。
0192名無しさん@お腹いっぱい。
2007/09/29(土) 11:44:02HP-UXのexprがsubstrをサポートしていないんじゃないの?
LinuxのはGNU coreutilsのexprを使っていることが多いので、
いろいろ拡張されているよ。
Macの/bin/exprもsyntax errorになった。
0193名無しさん@お腹いっぱい。
2007/09/29(土) 11:56:31>The use of string arguments _length_, _substr_, _index_ or _match_ produces unspecified results.
とあるな。未定義ということは、鼻から悪魔が出てきてもOK。
0194名無しさん@お腹いっぱい。
2007/09/29(土) 12:09:410195名無しさん@お腹いっぱい。
2007/09/29(土) 12:17:46>>192 193
よくわかりませんが、未定義の動作かも知れませんね。
0196名無しさん@お腹いっぱい。
2007/09/29(土) 12:28:35>>192
0197名無しさん@お腹いっぱい。
2007/09/29(土) 12:36:01ほとんど対応していないことが多いSolarisのexprでさえ、
substrには対応してる。POSIXがどう言っていようが、
業界標準的にはexprはsubstrが使えるべきだろう。
0198名無しさん@お腹いっぱい。
2007/09/29(土) 12:42:14ポータビリティ考えたら、exprじゃなく、
echo $A | cut -b1
を使うべきだな。
0199名無しさん@お腹いっぱい。
2007/09/29(土) 12:42:25確かに互換性を考慮するれば、使えるべきですね。
特定の場合だけ、エラーになるということは、(HP-UX)の不具合なのかも
知れませんね。
0200名無しさん@お腹いっぱい。
2007/09/29(土) 12:44:04別な方法があるのですね。勉強になります。
0201名無しさん@お腹いっぱい。
2007/09/29(土) 12:46:16古い cutでは -bオプションが使えない。
cut使うなら↓にするべき。
echo $A | LANG=C cut -c1
0202名無しさん@お腹いっぱい。
2007/09/29(土) 13:01:47変数$Aに "/etc 123" という文字列情報(空白がある)があった場合、
123を取り出したい場合は、どうすればよいでしょうか。
"AAA /etc 123"
"AAA BBB /etc 45"
という場合もあり、一番右側の数値だけを取り出したい場合です。
■ このスレッドは過去ログ倉庫に格納されています