トップページunix
985コメント289KB

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

■ このスレッドは過去ログ倉庫に格納されています
0001名無しさん@お腹いっぱい。2007/02/15(木) 14:28:44
シェルスクリプトの総合スレです。
スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(>>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 でトレースしましょう。

前スレ
シェルスクリプト総合 その7
http://pc10.2ch.net/test/read.cgi/unix/1157601611/
0263名無しさん@お腹いっぱい。2007/03/09(金) 21:47:41
配列も、位置パラメータも
所詮人間がデータ構造を解釈しているだけの話。
0264名無しさん@お腹いっぱい。2007/03/10(土) 21:31:59
201が宿題やったせいで254も宿題思われてるのかw
というより口だけで実は分からないだけですかおまいら。
0265名無しさん@お腹いっぱい。2007/03/10(土) 21:37:01
>>264
宿題かどうかが問題なんじゃなくて、cshのスクリプトは論外ということ。
誰も答えるはずがない。
0266名無しさん@お腹いっぱい。2007/03/10(土) 21:44:39
自演乙
0267名無しさん@お腹いっぱい。2007/03/10(土) 21:45:26
  / / ,. -'"´         `丶、、 ヽ
       __l //      /  |      \ \\ ゙、        / ̄ ̄ ̄ ̄ ̄ ̄
     / :::||  / / /    l l      ヽ ヽヽド、      /
    l::::::::::|| /   /  /      ! l  ヽ   ヽ ヽヽ ||:::::ヽ    |  l 十``  十_ヽ
   斤.::::::::||/  /   //! ハ  l  !  ヽ   ', ゙ヽ||::::::::勺    |  レ d、  (_| _)
   |ll|i :::::::|| l l  イ l /!l | ヽ  ト、|、  ト、  l  l、||::::::::}ll|   |  ┼‐、ヽ  ┴┴
   |ll|ヽ:::::|l  !l  |l!‐!‐ト、l  ヽ | l | ヽ | l i l  l||:::::::/!l|   |     ノ   月 l |
   |lll| `ー!  l  | l 」-=ミ|`ヽ ヽ | !-‐!‐|-l、|} l  |r、〃|ll|   |  二二``  l__ヽ
   L!l   |   l | 〃{ノ::::iヾ  ヽ! ,. =-ミ、!ハ l  !"´ |ll|   |   ノ     _)
         {l  |!l | ヽ `ー"     ' トイ:::}ヾ  | l |  |ll」   |   ─ァ
         ヽ |l !|               `二ノ  '| ||       |  /\
          l |', |                 /)|l l        |  ┼‐、ヽ
           l | ゙、        ` ´         /-イ| l          |    ノ
            !|  \    ヽニヽ      , ′/゙! l       ∠   '⌒)
         |   |ヽ、  ー     /  〃 | !         |   「
             ,.rr|   丶、   ,.. '´ト、     l′        ヽ  ゚
            l::l {:|     ` ´   |::}}               \______
        _. -‐1::ヽ' -、    _,.. -‐ン::|ヽ、
 _.. -‐ "´     |:::::::::`ゝヽ  /rJ::'"´:::::::!  ` 丶、
0268名無しさん@お腹いっぱい。2007/03/10(土) 21:52:54
だいたい木曜辺りに宿題が出るのか?
0269名無しさん@お腹いっぱい。2007/03/10(土) 22:04:01
宿題は2chでやってもらうのが当たり前です。
0270名無しさん@お腹いっぱい。2007/03/10(土) 22:11:17
逆に、宿題を出す立場の人間です。
毎回、問題を出すのにネタが尽き気味で大変です。
宿題が出た人、どんどんその問題を書き込んでください。
一部変えて出題に使わせていただきます。
0271名無しさん@お腹いっぱい。2007/03/10(土) 22:19:47
2ちゃんを使わせない方法
0272名無しさん@お腹いっぱい。2007/03/10(土) 22:29:26
>>270
分かった。
うちで使うスクリプトを問題として出してやる。
0273名無しさん@お腹いっぱい。2007/03/12(月) 10:34:35
>>270
tacをシェルスクリプトで書かせる。
0274名無しさん@お腹いっぱい。2007/03/12(月) 10:47:03
>>273
そういえば、まだ bash の回答がない。
ttp://golf.shinh.org/p.rb?reverse+lines
この問題にかぎらず、sh で参戦してる人が少ないのでおまいらもやってみてくれ。
おれもがんばってみる。
0275名無しさん@お腹いっぱい。2007/03/12(月) 17:31:24
sedの解が出てるんだからそれを呼べばよいのでは。
何も無理してshだけで文字列操作するこたーないと思うけど。
#!/bin/sh
f () { local l; read -r l && { f; echo "$l"; }; }
f
0276名無しさん@お腹いっぱい。2007/03/12(月) 18:28:56
>>275
readの -r オプションはbash依存。localコマンドは Bourneで使えない。
あと、再帰呼出しは重い。非再帰版の方がエレガント。
出題ネタにしたいので、回答は省略。
0277名無しさん@お腹いっぱい。2007/03/12(月) 18:44:38
#! /bin/sh

txt=
IFS='
'
while read line
do
txt="${line}
${txt}"
done
echo -n "$txt"
0278名無しさん@お腹いっぱい。2007/03/12(月) 19:10:00
>>276
CodeGolfが出ちゃったからbashism上等の答えになったんだと思う。

0279名無しさん@お腹いっぱい。2007/03/12(月) 19:18:19
localはどうか忘れたがread -rはPOSIXにもあったんじゃないか?
0280名無しさん@お腹いっぱい。2007/03/13(火) 01:40:57
そーすpls
0281名無しさん@お腹いっぱい。2007/03/13(火) 02:44:26
>>280
>>3
> POSIX: Shell & Utilities (標準規格)
> http://www.opengroup.org/onlinepubs/009695399/utilities/contents.html
0282名無しさん@お腹いっぱい。2007/03/13(火) 09:45:19
http://www.opengroup.org/onlinepubs/009695399/utilities/read.html
なるほどね
0283名無しさん@お腹いっぱい。2007/03/13(火) 20:53:58
awkについて質問します。
single quotation mark("'")をエスケープしたいのですが、
次のコードは×となります。
どなたか、どうやって、"'"をエスケープするのか
教えていただけますか?

たとえば、
awk '{printf "\'%s\'", $2}' file
として、
$2フィールドの値を
'AX'
'PY'
'CU'
のように''で囲みたいのです。
0284名無しさん@お腹いっぱい。2007/03/13(火) 20:57:48
シェルレベルで '...' と ¥' からなる並びに見えるようにする。

'{printf "'
¥'
'%s'
¥'
'¥n", $2}'

見やすいように改行入れてみたが実際にはくっつけて記述。
0285名無しさん@お腹いっぱい。2007/03/13(火) 21:15:45
>>284
できました!
ありがとう。
なんでできるのか、もう少し詳しく
教えていただけないでしょうか?
0286名無しさん@お腹いっぱい。2007/03/13(火) 21:48:08
awk に渡したい文字列を分解するだけだよ。
シェルの解釈する文字をエスケープしながらね。
だから、
'{printf "'"'%s'"'\n", $1}'
などでもいい。
0287名無しさん@お腹いっぱい。2007/03/13(火) 21:49:44
$1じゃなくて$2だったか
0288名無しさん@お腹いっぱい。2007/03/13(火) 22:15:15
wgetの実行結果をファイルに書き込みしたいんですけど
wget アドレス >>ファイル名
で実行して失敗しました。
どうしたらいいかわかりますか?
0289名無しさん@お腹いっぱい。2007/03/13(火) 22:19:00
わかりますよ。
0290名無しさん@お腹いっぱい。2007/03/13(火) 22:25:01
wget --help
0291名無しさん@お腹いっぱい。2007/03/14(水) 17:16:17
テキストファイルのある行が2chのdat形式かどうかを
正しく判別するにはどうすればいいでしょうか?

grep -E ".*<>.*<>[0-9]+/[0-9]+/[0-9].* [0-9:.]+ ID:[a-zA-Z0-9+-/]+<>.*<>.*"

こんな感じでひっかけようと思ったのですが、
何かの間違いでメール欄やレス欄に <> が
まぎれこんでしまってる場合でもマッチしてしまいます。
やりたいことは、このようなゴミのまじった行を削除することなのですが
どうするのがよいでしょうか?
0292名無しさん@お腹いっぱい。2007/03/14(水) 18:47:38
あ、しまった。
0293名無しさん@お腹いっぱい。2007/03/14(水) 21:33:18
> ゴミのまじった行を削除する

全部捨てたらいいんじゃないか。
0294名無しさん@お腹いっぱい。2007/03/14(水) 22:54:48
無理にシェルで書かんでもいいんでは。
0295名無しさん@お腹いっぱい。2007/03/14(水) 23:24:19
>>288

-O
0296名無しさん@お腹いっぱい。2007/03/15(木) 03:28:47
>>270
宿題にするな。テストにしとけ。
0297名無しさん@お腹いっぱい。2007/03/15(木) 09:45:11
ペーパーテストで一発完動のスクリプトかける奴なら即戦力だな。
0298名無しさん@お腹いっぱい。2007/03/15(木) 23:41:20
ShellScriptの中でscpとsshを使用しようと思っているのですが
普通に構文を書くとパスワード入力等を求められると思うのですが
手動入力でなく、完全自動化にできないでしょうか?
Shellは「sh」です。
OSはRedhatです
0299名無しさん@お腹いっぱい。2007/03/15(木) 23:42:09
>>298
ssh-agent
0300名無しさん@お腹いっぱい。2007/03/15(木) 23:53:17
ssh-agent を使用するしか方法はないですか?
他のプログラムとかの絡みで使用できるか・・・・
0301名無しさん@お腹いっぱい。2007/03/16(金) 00:12:20
リモートの.ssh/authorized_keyにローカルの公開鍵を書いとく
0302名無しさん@お腹いっぱい。2007/03/16(金) 00:13:16
>>298
板違い。
【sed】シェルスクリプト総合@LINUX Part2【awk】
http://pc11.2ch.net/test/read.cgi/linux/1154578200/

むしろこっちか。
くだらねえ質問はここに書き込め! Part 142
http://pc11.2ch.net/test/read.cgi/linux/1173460712/
0303名無しさん@お腹いっぱい。2007/03/16(金) 07:56:47
>>300
ssh-agentを知ってるなら質問するなよ!
0304名無しさん@お腹いっぱい。2007/03/16(金) 08:32:48
自分の鍵を暗号化しないでおくというのはどうだろう
0305名無しさん@お腹いっぱい。2007/03/16(金) 08:33:30
パスフレーズを空にする。
ただし、秘密鍵を盗まれないように。
0306名無しさん@お腹いっぱい。2007/03/16(金) 10:28:23
ssh-keychain は?
03073062007/03/16(金) 10:30:13
gentoo が作ってるやつな
http://www.gentoo.org/proj/en/keychain/
0308名無しさん@お腹いっぱい。2007/03/16(金) 22:01:18
>>298
expect
0309名無しさん@お腹いっぱい。2007/03/16(金) 22:13:13
困ったときは〜expect
0310名無しさん@お腹いっぱい。2007/03/18(日) 18:56:13
expectって標準ではいってたっけ?
0311名無しさん@お腹いっぱい。2007/03/18(日) 22:20:49
なんの標準だかわからんけど
入ってないなら入れればいいじゃん。
0312名無しさん@お腹いっぱい。2007/03/18(日) 23:45:58
>>310
お馬鹿さん?
0313名無しさん@お腹いっぱい。2007/03/20(火) 00:15:56
仕事の場合、そうホイホイと入れるわけにはいかないんだな
0314名無しさん@お腹いっぱい。2007/03/20(火) 00:34:23
じゃあしかたないな
0315名無しさん@お腹いっぱい。2007/03/20(火) 00:46:09
必要ないものはホイホイ入れられないだろうが
必要あるなら入れなきゃいかんだろ。
0316名無しさん@お腹いっぱい。2007/03/21(水) 00:06:29
あたらしい言語処理系が入るというと嫌がられそうだから、
perlの小さなライブラリを追加といってExpect.pmでよくない?
かなりプログラム臭くなるのでexpectに比べてはいけないが、次善の策ではあるはず。
0317名無しさん@お腹いっぱい。2007/03/21(水) 01:28:07
なんでexpect入れる話になってんだ
0318名無しさん@お腹いっぱい。2007/03/21(水) 01:51:29
今回は>>298からの流れ
0319名無しさん@お腹いっぱい。2007/03/21(水) 02:25:07
telnetならexpect使うのがいいだろうけど、sshとscpならパスなしのkeyを使うのが無難だと思うけどな。
パスなしでログインできるのが怖いなら、authorized_keysにcommandを書いて、できることを限定しておくといいよ。
スレ違いだったらすまん。
0320名無しさん@お腹いっぱい。2007/03/28(水) 01:47:01
sedで、最後の行から逆順に文字列検索していって、1件目を出力して終わらせることできるかな?
0321名無しさん@お腹いっぱい。2007/03/28(水) 02:04:06
cat hoge.txt | grep ほげ | tail -1
0322名無しさん@お腹いっぱい。2007/03/28(水) 02:30:58
>>320
awkでやれ
awk '{line[NR]=$0}END{for(i=NR;i>0;i--){if(line[i]=="検索パターン") print line[i];}}' input.txt
0323名無しさん@お腹いっぱい。2007/03/28(水) 02:50:52
tac filename | sed -n '/hoge/{p;q;}'
0324名無しさん@お腹いっぱい。2007/03/29(木) 16:52:36
二つのテキストファイルA.txtとB.txtがあります。
行数は同じでそれぞれの行が関係のある物になっています。
現在、その二つの行をそれぞれスペースで区切って接続を行いたく考えています。

A.txt
山田
山下

B.txt
太郎
二郎

AB.txt
山田 太郎
山下 二郎

A.txtとB.txtからAB.txtを作成する妙案などございましたらご教示いただけませんでしょうか?
よろしくお願い致します。

0325名無しさん@お腹いっぱい。2007/03/29(木) 16:56:53
>>324
paste A.txt B.txt > AB.txt
0326名無しさん@お腹いっぱい。2007/03/29(木) 17:09:44
>>325
PASTE(1)
名前
paste - ファイルを行単位でマージする

大変失礼いたしました…orz
シェルスクリプトとかそう言うレベルで無かったことをお許し下さい…。
0327名無しさん@お腹いっぱい。2007/03/30(金) 09:37:33
b.txt の内容で
幸子の場合、a.txtが山田となっていたら
里中に変更する。という条件付きくらいにしとけば
スクリプトでしなきゃいかんけどな。
0328名無しさん@お腹いっぱい。2007/03/30(金) 15:20:07
~/.forwardに記述して、メールを標準入力から読み込んで
そのenvelope Fromを、実データのFromに置換して/usr/bin/vacation
に渡すスクリプトを書きたいのですが・・・

sed -n 's/^From: [^<]*<\([^>]*\).*/\1/p'の内容を覚えさせておいて、
もう一度先頭から読み込んで置換すればよいと思いますが、
その方法がわからないのです。
微妙な内容なのでググるためのキーワードもいまいちで、ヒットしません。

別にsedでなくてpealやawkでもよいのですが、何かいい方法はありますでしょうか?
0329名無しさん@お腹いっぱい。2007/03/30(金) 15:26:46
>>328
そのまま
・覚えさせる->ファイルに書く
・もう一度先頭から読み込んで置換する->そうする
でいいんじゃないの?
0330名無しさん@お腹いっぱい。2007/03/30(金) 16:01:32
URLが一行ずつずらーと並んでいるのですが
頭とケツにそれぞれ「”」を付けたいです。
何か良い方法は有りませんでしょうか?
0331名無しさん@お腹いっぱい。2007/03/30(金) 16:08:36
sed 's/^/”/' | sed 's/$/”/'
0332名無しさん@お腹いっぱい。2007/03/30(金) 16:17:30
>>331
パイプが無駄。一発でできる。

sed 's/\(.*\)/"\1"/'
0333名無しさん@お腹いっぱい。2007/03/30(金) 16:24:13
pealのようなもの
03343282007/03/30(金) 16:31:53
>>329

難しく考えずに、そうすることにします。
0335名無しさん@お腹いっぱい。2007/03/30(金) 16:44:44
>>331-332
ありがとうございます。
頑張ってsed覚えます。
03363282007/03/30(金) 17:10:27
>>334

と思ったら、メール出力から起動されるプログラムは
きわめて弱い実行権限(nobody)しかないので、/tmpにさえ
ファイルを作れません。(人間がテストしたときは巧くいきましたが・・)
権限を強めればセキュリティーリスクが増大するし、
やはり、スクリプトの中で記録と標準入力の再読み込みが必要な模様です。
まあ記録は置換文字列に変数を使えることが判ったので何とかなりそうですが、
「初めからもう一度実行」が途方に暮れてしまいますね。

何かよい方法ありますでしょうか?
0337名無しさん@お腹いっぱい。2007/03/30(金) 17:14:32
・nobody でも /tmp に書ける。
・そもそも sendmail でも postfix でも .forward のファイル所有者と
同じ権限でプログラムが起動する。nobody にはならない。
03383282007/03/30(金) 18:36:24
>>337

なるほど

では、ほかの原因を考察して見ます。

ありがとうございます。
0339名無しさん@お腹いっぱい。2007/03/30(金) 22:30:53
>>335
sed 's/.*/"&"/'
でもいいな。
0340名無しさん@お腹いっぱい。2007/03/30(金) 23:05:57
>>335
正規表現は使わない方が速いかな。
awkで、
awk '{print "\""$0"\""}'
0341名無しさん@お腹いっぱい。2007/04/03(火) 01:43:34
awkのsystem関数に与えるコマンド文字列の中で「"」や「'」って使える?
「\」を前に置いても駄目でした…

0342名無しさん@お腹いっぱい。2007/04/03(火) 02:26:06
>>341
system が起動しているシェルに食われたんじゃね?
0343名無しさん@お腹いっぱい。2007/04/04(水) 00:17:45
>>342
例えばこんな感じ。実際はこんなシンプルじゃないけど。
awk '{system("grep \"^$\" $1")}' input.file
systemが食われたのか、systemの引数の中では引用符が使えないのか、切り分けができません。

0344名無しさん@お腹いっぱい。2007/04/04(水) 00:26:48
>>343の例だと$1に何も入らないから、とか?
0345名無しさん@お腹いっぱい。2007/04/04(水) 01:00:44
>>344
あそっか、$1は""の外でした。。

awk '{system("grep \"^$\" "$1)}' input.file

本物は業務で使う予定だからコピペできないんだよね。

0346名無しさん@お腹いっぱい。2007/04/07(土) 02:11:04
find /日本/関東/女/ mtime +7300でリダイレクトしたら彼女が出来た
0347名無しさん@お腹いっぱい。2007/04/08(日) 22:55:59
>>345
ちゃんと伝わっていなかったようで。
awkの中にシェルの変数の$1入れてもawkがもっていっちゃうからダメなんだって。
0348名無しさん@お腹いっぱい。2007/04/09(月) 22:22:34
>>347

そうか?普通に↓とか使えてるぞ?

awk '{sum[substr($0,a,b)]+=substr($0,c,d);}END{for(n in sum)print n,sum[n];}' input.txt

0349名無しさん@お腹いっぱい。2007/04/10(火) 20:40:57
なんかかみ合わないんだけど、
>>343>>345の例だと、$1をシェルがもっていっちゃって動かないだろうから、
本来やりたいことである
>awkのsystem関数に与えるコマンド文字列の中で「"」や「'」って使える?
の問題とは違ったところでハマっているでしょ、ってことを書いただけなんだけど。
($1にはinput.txtを入れたいのだろうと推測)

それに対して、$数字は awkで使用できるよ、と書かれても困っちゃうんだが。
0350名無しさん@お腹いっぱい。2007/04/11(水) 06:22:32
>>349
言いたいだろうことは理解するが、347がそれが伝わる書き方とは思えなかったぞ。
例えば、何を誰がもっていっちゃうと書いたか、347と349を比較してみ。
0351名無しさん@お腹いっぱい。2007/04/13(金) 00:00:33
ふいんき(なぜか略)を悪くしたようで正直スマンカッタ
0352名無しさん@お腹いっぱい。2007/04/13(金) 01:37:02
awkは読み込んだレコード全体を$0で参照できて、
フィールドセパレータ(デフォルト空白文字)で区切られたn番目のフィールドを
$nで参照できるんだよな。
awk '{system("grep \"^$\" "$1)}' input.file
で$1はinput.fileから読み込んだカレントレコードの1番目のフィールドを
参照すると。
$数字がawkで使えるのは良いとして結局"や'は
system関数の引数の中で使えるのかどうか?

0353名無しさん@お腹いっぱい。2007/04/13(金) 16:02:04
DebianとFreeBSDを使っていて、共通の.bashrcを参照しているのですが
Debianを使っているときにはUTF-8を、
FreeBSDを使っているときにはEUC-JPを
環境変数LANGに設定するようにしたいのですが
どのようにコードをかけばよいのでしょうか?
0354名無しさん@お腹いっぱい。2007/04/13(金) 16:07:45
>>353
uname とか hostname あたり見るとか。
03553532007/04/13(金) 16:42:04
>>354
unameとif文を使えばできると思うんですけど
それでsourceコマンドを実行したときに
ちゃんとわりあたるかどうか・・・
0356名無しさん@お腹いっぱい。2007/04/13(金) 16:54:07
>>355
おいおい、sourceなんて使わないよ。
あと、ifじゃなくてcaseを使うのが定石。

case `uname -s` in
Linux) export LANG=ja_JP.UTF-8;;
FreeBSD) export LANG=ja_JP.eucJP;;
esac
0357名無しさん@お腹いっぱい。2007/04/13(金) 16:55:19
別に if 使ってもいいと思うけど、
なんで source が出てくるのかよくわからん。
0358名無しさん@お腹いっぱい。2007/04/15(日) 15:34:49
>>356
Cとかだとswtichは敬遠される傾向にあるけどな。
0359名無しさん@お腹いっぱい。2007/04/15(日) 17:19:24
お前の周りだけだろ。
0360名無しさん@お腹いっぱい。2007/04/15(日) 17:33:16
ifを使うとすると、

if [ `uname -s` = Linux ]; then
export LANG=ja_JP.UTF-8
elif [ `uname -s` = FreeBSD ]; then
export LANG=ja_JP.eucJP
fi

となって、unameの実行が2回になって無駄になる。
かと言ってunameを1回にしようとすると、

tmp=`uname -s`
if [ $tmp = Linux ]; then
export LANG=ja_JP.UTF-8
elif [ $tmp = FreeBSD ]; then
export LANG=ja_JP.eucJP
fi

となって、シェル変数1つが余分に要るので美しくない。

よって、caseを使うのがモストエレガント。
0361名無しさん@お腹いっぱい。2007/04/15(日) 17:37:03
>>360
お前の美学はよくわかった。
0362名無しさん@お腹いっぱい。2007/04/15(日) 17:41:22
で、source はなんで出てきたんだ?
■ このスレッドは過去ログ倉庫に格納されています