トップページunix
1001コメント327KB

シェルスクリプト総合 その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/
0532名無しさん@お腹いっぱい。2007/12/06(木) 00:23:08
つっこんだら負けかなと思っている
0533名無しさん@お腹いっぱい。2007/12/06(木) 00:45:46
>>531
オマイそんなこと知らないで
よく今までスクリプト組めたな

罰として、まずモナスクリプト書け
等幅フォント用とモナフォント用だ
05345312007/12/06(木) 00:50:49
いや、半角空白の連続が消える、ってここ(2ch)の話。
0535名無しさん@お腹いっぱい。2007/12/06(木) 01:16:01
そういう時はこう書く
Hello World
Hello  World
Hello   World
0536名無しさん@お腹いっぱい。2007/12/06(木) 07:50:42
>>527
できました!! xmessageにしたらシェルが出ました
でも本には echoって書いてあったんですよ。ミスプリでしょうか?
0537名無しさん@お腹いっぱい。2007/12/06(木) 08:52:37
そういうネタはいいから。
0538名無しさん@お腹いっぱい。2007/12/09(日) 21:07:10
シェルスクリプトでキー入力なんかを実行できますか?(bash)
例えば、moreコマンドなんかの後のスペースキーだとかを

more /hoge/a.txt <<EOF
???
???
???
EOF

なんかで出来ないものでしょうか?
よろしくお願いします。
0539名無しさん@お腹いっぱい。2007/12/09(日) 21:17:20
expect使え。
0540名無しさん@お腹いっぱい。2007/12/10(月) 13:18:59
シェルは日常使い、fortranは全くの初心者の質問です。
1000回程度のループ計算なんですが、計算式部分はfortranでサンプル拝借、代入&出力処理をシェルで書いてみました。
なんとなく出来上がったんですが、ひとつ疑問が浮上し、すぐに解決出来ないのでアドバイス下さい。

fortran90で全て書いた場合と、どの程度速度は劣るのでしょうか?
0541名無しさん@お腹いっぱい。2007/12/10(月) 13:43:38
このスレで聞くのが適切だと考えた理由は何ですか?
05425402007/12/10(月) 14:34:13
シェルスクリプトに精通しているのはこのスレの住人だからです。
他のスレではシェルを使っている人がいるか居るのか定かではありません。
僕のような2通りの方法で書いて比較した経験のある方がいらっしゃるのでは?
という淡い期待を持って質問した次第です。
すみません。スレ違いならこの質問は脚下でいいです。
0543名無しさん@お腹いっぱい。2007/12/10(月) 20:39:20
シェルってゆうな。クズ。
0544名無しさん@お腹いっぱい。2007/12/10(月) 21:16:20
>>542
 気になるなら自分で実測するのが確実。
(shの走る環境の、CPU性能メモリ量の差は非常に幅広いため、答えがない)
0545名無しさん@お腹いっぱい。2007/12/10(月) 21:22:53
同じ環境でのshとfortranとの比較だから、
CPU、メモリの差による違いは直接関係ないと思うが。
0546名無しさん@お腹いっぱい。2007/12/10(月) 21:32:37
>>545

>>542で「僕のような2通りの方法で書いて比較した経験のある方が」と言っている。

CPUやメモリ量が異なる環境での結果と、質問者の環境での結果を、比較しても無意味だ。
(ARM上の結果とCell上の結果を比較しても意味なかろ)
0547名無しさん@お腹いっぱい。2007/12/10(月) 21:43:10
>>546
どんなCPU/メモリ環境であろうが、
shとFortranとの速度差は同じような傾向になる。

よって、「CPU性能メモリ量の差は非常に幅広い」としても、
それは質問の本質には関係ない。答えはある。
0548名無しさん@お腹いっぱい。2007/12/10(月) 21:47:29
>>546
ARM上のshとFortranとの比較データがあれば、
それはCell上のshとFortranとの速度差(比)を推定する手がかりになる。
よって、大いに意味ある。
0549名無しさん@お腹いっぱい。2007/12/10(月) 21:52:02
fortranで書いた計算部分とループの部分の時間比を考えないのは
ゆとり教育の成果か?
0550名無しさん@お腹いっぱい。2007/12/11(火) 14:32:22
教えてください。
bshで、あるテキストを2行ごとに1行にまとめたいのです。
たとえば、
$ cat aaa.txt
aaa
bbb
ccc
ddd
eee
fff



$ cat bbb.txt
aaa bbb
ccc ddd
eee fff

にしたいのです。
sedで置換したり、whileで回したりとかいろいろあるでしょうけど
確かコマンド一つで出来た記憶があるのです。

$ cat aaa.txt | コマンド . . > bbb.txt

うろ覚えですが、そのコマンドにパラメータを二つ(ドットを二個)で、
2行を1行にまとめる。。。だったような気がするのですが、
知っている人いたら教えてください。
0551名無しさん@お腹いっぱい。2007/12/11(火) 14:40:28
>>550
paste - - か?
あと、cat | じゃなく < でおk。
0552名無しさん@お腹いっぱい。2007/12/11(火) 14:44:12
そうです!!
pasteです。完全に思い出しました! そうですね、ハイフンですね。
すばやいレスありがとうございました。
0553名無しさん@お腹いっぱい。2007/12/11(火) 18:00:20
cat /tmp/test.txt | gawk 'NR%2 {s = $0} !(NR%2) {print s" "$0}'
0554名無しさん@お腹いっぱい。2007/12/11(火) 18:04:40
これテンプレに入れといてくれ。
http://www.netmeister.org/misc/useless_use.pdf
0555名無しさん@お腹いっぱい。2007/12/12(水) 01:57:08
教えてください。
A
B
C
とあって、
2行目の下(この場合はBの下)に
BB
を入れて、
A
B
BB
C
とする
指定行数の下に文字列を挿入する
シェルスクリプトを作りたいのですが、
なにか良いアイデアはないでしょうか?
0556名無しさん@お腹いっぱい。2007/12/12(水) 02:22:17
指定行(2行目)の後に文字列(BB改行)を挿入するには、

sed '2a¥
BB
' < old > new

のようにすればできる。

行と挿入する文字列を変数展開するようにすればいいんじゃね?
0557名無しさん@お腹いっぱい。2007/12/12(水) 02:22:57
oldの前の<はいらなかった。
0558名無しさん@お腹いっぱい。2007/12/12(水) 22:55:42
cat /tmp/test.txt | awk -vSTR='BB' -vL=2 '{print} NR==L{print STR}'
0559名無しさん@お腹いっぱい。2007/12/13(木) 02:40:12
文字列処理についての質問です。

以下のHTMLタグがあるとします。
<option name=myname value="a1">b1</option>
<option name=myname value="a2">b2</option>
<option name=myname value="a3">b3</option>

上記の中から文字列処理を行い、以下の結果を導き出したいです。
a1,b1
a2,b2
a3,b3

このようにするにはどのように処理すればよろしいでしょうか?

よろしくお願いいたします。
0560名無しさん@お腹いっぱい。2007/12/13(木) 03:12:04
cat /tmp/test.html | perl -nle '/value="([^"]+)">([^<]+)</ && print "$1,$2"'
0561名無しさん@お腹いっぱい。2007/12/13(木) 08:25:29
htmlに微妙に変わっててわろたが、どっちもcatはいらん

>>559
ほんとうにこの例だけなら、
sed -e 's/.*="//' -e 's/">/,/' -e 's/<.*//'
0562名無しさん@お腹いっぱい。2007/12/14(金) 00:10:27
diffとawkを使って、10秒ごとにサーバに接続しているユーザ情報を取得し、ユーザのログインログアウトを監視するシェルスクリプトを教えてください
0563名無しさん@お腹いっぱい。2007/12/14(金) 00:14:43
宿題は自分でやりなさい
0564名無しさん@お腹いっぱい。2007/12/14(金) 01:21:16
お願いします
m(__)m
全然分からなくて…
0565名無しさん@お腹いっぱい。2007/12/14(金) 01:40:44
diffとawkの知識だけじゃできないなあ
wとかwhoとかlastとか調べてみるといいかもしれん
0566名無しさん@お腹いっぱい。2007/12/14(金) 01:48:27
>>559
そういうのは普通E4X

var x = <html>
<option name="myname" value="a1">b1</option>
<option name="myname" value="a2">b2</option>
<option name="myname" value="a3">b3</option>
</html>;
for each (var opt in x.option) {
print("" + opt.@value + "," + opt);
}

じゃなかったらXSLT
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; version="1.0">
<xsl:template match="/">
<xsl:apply-templates select="*"/>
</xsl:template>

<xsl:template match="option">
<xsl:value-of select="@value"/>,<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
0567名無しさん@お腹いっぱい。2007/12/14(金) 01:50:22
#!/bin/sh

while true; do
  if [ ! -f /tmp/last.txt ] ; then
    touch /tmp/last.txt
  fi
  mv /tmp/last.txt /tmp/last.txt.old

  last > /tmp/last.txt

  diff /tmp/last.txt.old /tmp/last.txt
  sleep 5
done

基本はこんな感じか。これでもログイン/ログアウトの度に反応がでる。
あとは画面を生diffの結果から、も少し整形する必要があるわな。

< user pts/3 192.168.0.1 Fri Dec 14 01:43 still logged in
---
> user pts/3 192.168.0.1 Fri Dec 14 01:43 - 01:43 (00:00)

行の頭からログイン時刻までを一本の文字列にしてawkとかの連想配列のキーにして、
ログアウト時刻(またはstill logged inn)を保持しておくか...
あとlastのお尻の方はだんだん削られていくから、これも何とかする必要があるな。
0568名無しさん@お腹いっぱい。2007/12/14(金) 02:00:24
あるいはもう面倒くさいから

  diff /tmp/last.txt.old /tmp/last.txt > /dev/null 2>&1

  if [ $? -ne 0 ] ; then
    clear
   cat /tmp/last.txt
  fi

こうやっちゃうとかな。監視コンソール風。
0569名無しさん@お腹いっぱい。2007/12/14(金) 03:19:03
>>567
また俺のIPがサンプルに使われてる(´・ω・`)
攻撃の的になるからやめてよ
0570名無しさん@お腹いっぱい。2007/12/14(金) 03:38:51
つまらんボケにはつっこむ気も起きん
0571名無しさん@お腹いっぱい。2007/12/14(金) 04:26:20
>>569
最近、インターネットにアクセスできないと思ったらお前のせいかー
0572名無しさん@お腹いっぱい。2007/12/14(金) 09:18:48
●でログインしてもここの過去スレにアクセスできないんですが、
過去スレ保存している人いませんかね?
0573名無しさん@お腹いっぱい。2007/12/14(金) 11:52:49
1から8までとってあるよ。
0574名無しさん@お腹いっぱい。2007/12/15(土) 01:59:33
適当な場所が見つからなかったので@wikiに作ってみました。
http://www32.atwiki.jp/shellscript/
よかったらここにアップしていただけないでしょうか。
0575名無しさん@お腹いっぱい。2007/12/16(日) 11:59:59
find / -regex "/home/[a-z0-9\-]/text/[a-z0-9.\-]\.txt" > text_list
で /home/***/text/***.txt
を探しているのですが、
どうもかなり遅めでload averageもあがりやすいようです。
ls あたりで代替策を探してるのですが、
ls /home/*/text/*.txt
あたりが良いかなと思ったのですが、*は/も含むと聞いて困ってます。
(試したところ、速度はfindと比べてかなり早かったのですが。。。)

どなたか助言お願いします。
0576名無しさん@お腹いっぱい。2007/12/16(日) 13:07:30
> *は/も含むと聞いて困ってます。
ヤキいれてあげるから、そういうデタラメを教えた奴を連れてきなさい。
0577名無しさん@お腹いっぱい。2007/12/16(日) 13:13:56
>>575
locate (+grep)とか。
0578名無しさん@お腹いっぱい。2007/12/16(日) 15:13:40
>>576
-regexの * は / も含むよw

ヤキいれられるのはオマエww
0579名無しさん@お腹いっぱい。2007/12/16(日) 15:21:47
>>578
日本語読めない低脳は引っ込んでいなさい。-regexの*の事ではない。

> ls /home/*/text/*.txt
> あたりが良いかなと思ったのですが、*は/も含むと聞いて困ってます。
0580名無しさん@お腹いっぱい。2007/12/16(日) 21:15:33
find -regex "...*..."
の場合、*は/を含む(ディレクトリ階層を縦断する)

ls */*
の場合、*は/を含まない(/で区切られたディレクトリ階層だけを探す)
0581名無しさん@お腹いっぱい。2007/12/16(日) 23:34:21
すみません。FreeBSDですが
文字列「aaa」と書いた1.txtをsedで「bbb」に変えて保存したい。
どのようにしたらいいでしょうか?
0582名無しさん@お腹いっぱい。2007/12/16(日) 23:38:27
sed -i -e 's/aaa/bbb/' 1.txt
05835812007/12/16(日) 23:51:33
>>582
-eが必要だったのか!でも-eは複数コマンドのオプションだと思ってた。
とにかくありがとう!
0584名無しさん@お腹いっぱい。2007/12/17(月) 01:04:43
たびたびすみません。FreeBSDですが
文字列「aaa\taaa」←水平タブ入りが書いてある1.txtを
文字列「bbb\tbbb」に変えて保存したい。
どうしたらいいでしょうか?
エスケープシーケンス入りの文字列の扱いがわからない。。。
0585名無しさん@お腹いっぱい。2007/12/17(月) 03:28:20
sed -i -e 's/aaa/bbb/g' 1.txt

タブ・エスケープは関係ない。/gをつけるとマッチしたもの全てを置換する(globalのg)。
gなしだと最初の一個だけ
05865842007/12/17(月) 05:11:44
>>585
じゃ、じゃあ

文字列aaaを

aaa
bbb

のように改行付きで置換したいとき

sed -i -e 's/aaa/aaa\nbbb/g' 1.txt
としても改行されません。
FreeBSDのsedはエスケープシーケンス使えない?
0587名無しさん@お腹いっぱい。2007/12/17(月) 06:24:56
% cat /tmp/1.txt
aaa
% sed -e 's/aaa/aaa\nbbb/g' /tmp/1.txt
aaa
bbb
% sed --version
GNU sed 4.1.1版

Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE,
to the extent permitted by law.
(後略)
05885732007/12/17(月) 09:51:07
>>574
アップロードしてみました。
shellscript.tar.bz2
05895732007/12/17(月) 10:00:25
8が最後まで入ってなかったのと、まちがえて現行スレまで入れてしまったので、
アップロードし直した(shellscript_.tar.bz2)
0590名無しさん@お腹いっぱい。2007/12/17(月) 10:30:05
>>586
\を前置して改行をそのまま書く。

% echo aaa|sed 's/aaa/aaa\
bbb/'
0591名無しさん@お腹いっぱい。2007/12/18(火) 03:47:42
すいません。

scriptコマンドでコマンドログをとりたくて、ログイン時に自動的に呼び出されるよう
profileに書きましたが、ターミナルを終了する時にexitを何回も打たなくてはならないのが
気持ち悪いです。

例えば、一回のexit入力で、scriptとログインシェルの2回分を実行するというのは可能ですか?
0592名無しさん@お腹いっぱい。2007/12/18(火) 07:11:01
>>591
exec script
0593名無しさん@お腹いっぱい。2007/12/18(火) 07:42:32
>>592

ありがとう
0594名無しさん@お腹いっぱい。2007/12/18(火) 20:27:05
ファイルを読んでそのフィールドの一部分でuniqしたいんですけど、
どうすればよいですか?

APPLE,150円
APPLE,140円
APPLE,180円

とあったら、1フィールド目のみでuniqして先頭の行を出力したいです。
もちろん値段もほしいです。
ご教示お願いします。
0595名無しさん@お腹いっぱい。2007/12/18(火) 20:29:22
>>594
perl かなんかで書いちゃった方が早いんじゃね。
0596名無しさん@お腹いっぱい。2007/12/18(火) 20:31:18
awk 'BEGIN {FS=","} {if (foo != $1) {print}; foo = $1}'
0597名無しさん@お腹いっぱい。2007/12/18(火) 20:34:35
>595,596
早っ! ご教示ありがとございます
awkにします
0598名無しさん@お腹いっぱい。2007/12/18(火) 21:00:26
知ったかの >>595 が不憫。
0599名無しさん@お腹いっぱい。2007/12/18(火) 21:04:49
別に awk でできないとは言ってないよ。
0600名無しさん@お腹いっぱい。2007/12/18(火) 22:02:22
cat /tmp/file | perl -nle '$foo ne (@foo=(split/,/))[0] && (print, $foo=$foo[0])'
0601名無しさん@お腹いっぱい。2007/12/18(火) 22:25:21
久々に「catが無駄です」
0602名無しさん@お腹いっぱい。2007/12/18(火) 22:26:41
まあいいじゃん
0603名無しさん@お腹いっぱい。2007/12/18(火) 23:53:32
>>595
しね
0604名無しさん@お腹いっぱい。2007/12/18(火) 23:57:25
>>595=>>599
しね
二度と現れるなボケ
0605名無しさん@お腹いっぱい。2007/12/19(水) 00:46:05
awkがスクリプト言語と知らなかった598が顔を真っ赤にして暴れるスレ
06065952007/12/19(水) 00:54:10
なんかマズいこと言ったか?
よく知らないシェルスクリプトでがんばるより
便利で得意な言語で書いちゃった方が早いこともあるよ、
ってだけの話なんだけど。
0607名無しさん@お腹いっぱい。2007/12/19(水) 00:57:45
>>605
>>598じゃねーよw
おまえ、二度と現れるなと言っただろ?w
0608名無しさん@お腹いっぱい。2007/12/19(水) 01:01:44
>>595
おまえまだわかんねーのかよ?
おまえが言ってることは「ググレカス」と同レベル
どんな質問でも当てはまってしまうアホな回答。
0609名無しさん@お腹いっぱい。2007/12/19(水) 01:06:00
595じゃないが、>>608がなんで暴れてるのかよくわからん
0610名無しさん@お腹いっぱい。2007/12/19(水) 01:07:07
頭悪いからだろ。
0611名無しさん@お腹いっぱい。2007/12/19(水) 01:48:57
>>608じゃないが
>>595は自演が下手だな
こんな時間に過疎スレで1分後にレスって明らかに自演。
06125952007/12/19(水) 02:03:18
>>611
いや、>>595>>599>>606しか書いてないけど。
0613名無しさん@お腹いっぱい。2007/12/19(水) 02:19:31
perlには-aというオプションもあってだな。
0614名無しさん@お腹いっぱい。2007/12/19(水) 02:41:34
perlにはa2pという支援ツールがあってだな。
0615名無しさん@お腹いっぱい。2007/12/19(水) 02:49:04
awkのカーニハン本は言語の説明は1章だけで終わりで
あとは応用例だが、
perlのラクダ本は電話帳みたいな本が上下2巻。クックブックは別にある。
よってawkの勝ち
0616名無しさん@お腹いっぱい。2007/12/19(水) 02:57:18
perlは大体わかるけどawkはさっぱりです。
0617名無しさん@お腹いっぱい。2007/12/19(水) 03:12:02
>>615
awkの原典は、初学者が手にするとちょっとな。途方にくれるというか何というか。高い本なのに。
perlのラクダ本はその点は抜かりなく、初心者もすんなりと中に入り込んでいける。
awkの入門書で良書というと、ASCIIのawk256倍本くらいしか思いつかない。俺は今でも愛用してるけど、
あんな昭和の時代の本、いまどき手に入るはずもなく
0618名無しさん@お腹いっぱい。2007/12/19(水) 03:17:31
SED&AWKも忘れないで by おら
0619名無しさん@お腹いっぱい。2007/12/19(水) 03:49:30
>>618
その本初心者でもわかりやすい?
0620名無しさん@お腹いっぱい。2007/12/19(水) 10:07:59
>>594
perl -aF, -nle '$X{$F[0]} or print; $X{$F[0]} = 1'
0621名無しさん@お腹いっぱい。2007/12/19(水) 12:19:59
perlって見ためが汚いねw
0622名無しさん@お腹いっぱい。2007/12/19(水) 12:39:17
sedの置換について質問
タブ(\t)は置換できるのですが改行(\n)が置換できません。
例えば # cat a.txt
aaa
bbb
aaa(タブ)bbb

3行目の(タブ)区切りは置換できるけど1行目と2行目にマッチした文字を置換できません。
sedじゃ無理?こういうのawkでできたりしますか?
0623名無しさん@お腹いっぱい。2007/12/19(水) 12:47:27
>>622
sedについてはこちらへ

sed
http://pc11.2ch.net/test/read.cgi/unix/1085730992/
0624名無しさん@お腹いっぱい。2007/12/19(水) 12:56:24
cat /tmp/a.txt | awk '{sub("$", "<CR>"); sub("\t", "<TAB>"); print}'
0625名無しさん@お腹いっぱい。2007/12/19(水) 13:09:34
だから、catが(ry
ファイル名を前にもってきたいなら、せめて、
< /tmp/a.txt awk ...
と書け。
0626名無しさん@お腹いっぱい。2007/12/19(水) 13:21:07
>>554読んどけ。
0627名無しさん@お腹いっぱい。2007/12/19(水) 15:50:37
>>621
そうか?
0628名無しさん@お腹いっぱい。2007/12/19(水) 21:32:17
質問です。

a.txtの内容
----------
aaa
bbb
ccc
bbb
----------

このa.txtを
----------
aaa
bbb
ccc
ddd
----------
↑のようにa.txtを置換して保存したい。
この文字は何行目にあるか不明だとして
一番下のbbbをdddに置換することはできますか?sedでもawkでもいいのです。
2chなのになぜかたらい回しにされてるのですがよろしくお願いします。
0629名無しさん@お腹いっぱい。2007/12/19(水) 22:00:52
#!/bin/sh
ed a.txt << EOS > /dev/null
\$a

.
?bbb?c
ddd
.
\$d
wq
EOS
いったん末尾に1行挿入するのがコツ
06306282007/12/19(水) 22:06:31
1行のコマンドで出来ないものでしょうか?
0631名無しさん@お腹いっぱい。2007/12/19(水) 22:33:42
>>619

かなり、とっつきは悪い。
特にsed編は、使用目的がtroffマクロの置換とか、プリンタ整形言語の整形とか、訳分からん。
awk編はまあ、用例も身近なのが結構有るけど・・・

でも、内容は極めて濃い。
金を出して購入し、何度も読み返す価値は有ると思う。
■ このスレッドは過去ログ倉庫に格納されています