1 :名無しさん@お腹いっぱい。2011/06/16(木) 12:38:47.74
シェルスクリプトの総合スレです。
スクリプトのお勉強・自慢・腕試しなどにどうぞ。

□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
 Linuxユーザは/bin/shの正体がbashなので特に注意。
 FreeBSDユーザは/bin/shの正体がashなので注意。
 v7 shに一番近くて、現役のshは、OpenSolaris由来のheirloom sh。
  http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/sh/
  http://heirloom.sourceforge.net/sh.html
・csh/tcshのシェルスクリプトは推奨されません。
 (理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
 manや参考リンクを見ましょう。
 aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルスクリプトのことをシェルってゆーな
・シェルで使えるワイルドカード等は正規表現ではありません。
 正規表現の話題はスレ違い(正規表現スレへ)

□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
 RubyやPerlの方が適した仕事には素直にそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。

前スレ
シェルスクリプト総合 その17
http://hibari.2ch.net/test/read.cgi/unix/1290209379/
439 :名無しさん@お腹いっぱい。2011/09/04(日) 08:03:40.42
>>1のお約束について
Ubuntuのデフォルトが"dash"っになってたような気がするんだけども・・・それは書かなくていいのか?
2 :名無しさん@お腹いっぱい。2011/06/16(木) 22:26:41.84
職場での話しです。

シェルスクリプトが使える環境から一部別ネットワークで
作業をする羽目になった。

windoze環境なのは相変わらずだが、旧環境はかろうじてcygwinが使用できたが
新環境は「管理者が親切にrubyだけ入れてくれた」状態。

ま、多少高速に動きますけどね・・・
構文の見た目が糞なのだが、
俺のポーティングが悪いのかなぁ?

ファイルをsedで置換して別ファイルに書き込むとかは、
(裏でopenとかwriteとかいっぱいioctrlがcallされているか知らんが)
見た目はシェルスクリプトが百万倍スマートだと思う。
3 :名無しさん@お腹いっぱい。2011/06/16(木) 22:50:28.09
Rubyあるだけでも随分マシなほう
素のコマンドプロンプトはマジで何もできんからな…
20 :名無しさん@お腹いっぱい。2011/06/29(水) 21:33:35.45
>>3
そりゃそうだけど。
shellscriptのテストをshellscriptで書くのは、
コマンド群の出力を別のコマンド群に食べさせて
おなかを壊さなければ安心みたいな感じだけど、
rubyのテストをrubyで書いたり、
perlのテストをperlで書いたりとかは、
なんか辻褄だけは合って当然ぽくて
安心できない。

素のコマプロしかない作業環境になったら
転職します。
4 :名無しさん@お腹いっぱい。2011/06/16(木) 23:34:00.91
質問です。


hoge="a b c d"
for m in `echo $hoge`
do
echo $m
done

↑これと同じようなことを、
hoe="a,b,c,d"
↑これみたいにカンマ区切りのデータでやりたいんですが、どうすればいいですか?
5 :名無しさん@お腹いっぱい。2011/06/16(木) 23:40:48.99
IFS=,

hoe つまり、エミッタ接地時の出力アドミッタンスだな
6 :名無しさん@お腹いっぱい。2011/06/16(木) 23:48:15.67
>>5
ありがとうございます!
7 :>>42011/06/16(木) 23:54:02.88
うーん、だめでした。。

~$ cat hoge.sh
#!/bin/sh
IFS=,

hoge="a,b,c,d"
for m in `echo $hoge`
do
echo "m=$m"
done

~$ ./hoge.sh
m=a b c d

12 :名無しさん@お腹いっぱい。2011/06/19(日) 04:55:30.78
>>7
> for m in `echo $hoge`
echoを使う必然性は? 単に for m in $hoge なら期待通りじゃないかと思うけど。

> for m in `echo $hoge`
この場合、
(1) バッククォート中の展開するとき IFS=,だから echo a b c d になる。
(2) その出力"a b c d"を受けた元のシェルが単語分割する際も
IFS=,なので空白で分割されず、単一の文字列のまま。
ということで for m in 'a b c d' と同じになってしまうわけ。

IFSを使うなら処理のステップを分解してIFSの影響範囲を最小限に限定すると安全。
output=`なにか,区切りの出力をするコマンド`
IFS=, set -- $output
for m; do
  ...
done
9 :名無しさん@お腹いっぱい。2011/06/17(金) 00:27:58.76
下のやつはshとbashは同じだな。
zshはなんか他と違う。
jshもまた違う。

#!/bin/sh
IFS=,
hoge="a,b,c,d"
for m in a,b,c,d; do echo "m=$m"; done
for m in $hoge; do echo "m=$m"; done
for m in `echo a,b,c,d`; do echo "m=$m"; done
for m in `echo $hoge`; do echo "m=$m"; done
for m in "`echo a,b,c,d`"; do echo "m=$m"; done
for m in "`echo $hoge`"; do echo "m=$m"; done
10 :名無しさん@お腹いっぱい。2011/06/17(金) 10:11:22.76
>for m in `echo $hoge`

こんなことやって気にならないなら、

for m in `echo $hoge | tr , \ '

でいいんじゃないの? 俺はイヤだけど。
13 :名無しさん@お腹いっぱい。2011/06/28(火) 20:21:08.07
質問です。

solaris10のグローバルゾーンからローカルゾーンでループ処理を実行したいのですが、

zlogin zone コマンド

のコマンドの部分に、
例えば
for a in `cat a.log` do
echo $a
done
のような処理を入れようとすると
ローカルゾーンにログインしようとしてエラーになります。

関数とかにループ処理を格納して無理やり実行しようとしても駄目でした…

何か良い方法ありませんか?
使用シェルはbashです。
19 :名無しさん@お腹いっぱい。2011/06/29(水) 07:45:18.42
>>13
自己レスですが解決しました。
for a in `zlogin zone コマンド`
do
zlogin zone echo $a
done
みたいな感じにしてやれば
グローバルからルーブ処理実行できますね。
14 :名無しさん@お腹いっぱい。2011/06/28(火) 20:28:19.77
zloginのmanに↓と書いてあるから、manual読むのが一番の近道だと思うな。

Non-Interactive Mode
If a utility is specified, zlogin
operates in non-interactive mode.
This mode can be useful for script
authors since stdin, stdout, and
stderr are preserved and the exit
status of utility is returned upon
termination.
15 :名無しさん@お腹いっぱい。2011/06/28(火) 21:18:32.94
>>14
早速の返事ありがとうございます。
まぬある見てみたけど対話型無理って書いてあったからグローバルゾーンから複雑なコマンド実行は無理そうですね
かなり面倒だが一行づつ実行するしかないのかorz
16 :名無しさん@お腹いっぱい。2011/06/29(水) 00:59:14.86
bashで質問です。

ssh user@host echo $HOGE_PATH

で、ローカルのHOGE_PATHではなく、ssh先のHOGE_PATHを参照することってできますか?
17 :名無しさん@お腹いっぱい。2011/06/29(水) 01:09:51.64
>>16
ssh user@host echo '$HOGE_PATH'
とか
ssh user@host 'echo $HOGE_PATH'
とか
18 :名無しさん@お腹いっぱい。2011/06/29(水) 01:53:12.27
>>17
おおお、そういう事ができるんですね。
確かにssh先のが参照できました。なるほどー
23 :名無しさん@お腹いっぱい。2011/07/07(木) 19:31:33.14
ls -l

合計 100
とか
total 100
とか表示されるけど、この意味は何ですか?
24 :名無しさん@お腹いっぱい。2011/07/07(木) 19:35:26.48
>>23
ls -s で表示される数字の合計。
25 :名無しさん@お腹いっぱい。2011/07/07(木) 20:34:31.94
>>24
それは知ってるけど、それが ls -l の時に表示される意味は何ですか?
27 :名無しさん@お腹いっぱい。2011/07/08(金) 03:10:33.74
>>24
なるほど、ありがとうございます。
28 :名無しさん@お腹いっぱい。2011/07/08(金) 23:21:49.48
ubuntu10.10の標準状態です。
経験値は極めて低いです。
ZIPファイルを展開して処理して再圧縮させたいです。
展開したフォルダだけの名前を取得したいのですが、どうやればいいんですか?
echo *

echo *.*
比べるぐらいしか思いつかないです。。。
29 :名無しさん@お腹いっぱい。2011/07/08(金) 23:51:19.51
>>28
zip ファイルの中身の確認は
unzip -l hoge.zip
unzip -tv hoge.zip
などで確認

手軽にやるなら、fuse-zip を利用するのもあり
$ fuse-zip hoge.zip mountdir
$ 必要な処理
$ fusermount -u mountdir
でできる

unzip/zip コマンドで一部ファイルのみ変更する方法はあるのかな?
30 :名無しさん@お腹いっぱい。2011/07/08(金) 23:51:28.22
>>28
man basename
31 :名無しさん@お腹いっぱい。2011/07/09(土) 06:43:49.44
>>28
unzip展開後、find . -type d


>>30
お前は誰に何を答えてるんだw
manで答える回答は外してる、の法則の成立例。
32 :名無しさん@お腹いっぱい。2011/07/09(土) 08:34:08.18
>>31
普通そこらへんにzip展開してファイルを産卵させることないから、
WORKDIRに展開するとして、こうしないかな?スクリプトから使うことも考えると。
find "$WORKDIR" -type d
34 :名無しさん@お腹いっぱい。2011/07/09(土) 09:34:51.11
>>29-33
ありがと。
キーはfind -type d
だね。
ついでに聞きたいけど、
シェルスクリプトの入門書ってなにかいい本ある?
javaとかcgiの本は本屋でいっぱい見かけるけど。。。
どんなコマンドがあるか把握するだけでもちょっと大変。

面白いけど。
43 :名無しさん@お腹いっぱい。2011/07/10(日) 16:59:24.56
>>34
大学の図書館でいろいろなコマンドの説明が書いてあるハンドブックを読んだことがある。タイトル忘れた。
ウィキペでちょっとアレだが、ここにあるコマンドで大体必要な処理は書けるよ。
ttp://ja.wikipedia.org/wiki/Template:Unix%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89
exprとか地味によく使うコマンドの説明がなかったりするけど、
詳しい説明はman読んだほうが、どんなサイトや本の説明よりいいかと。
35 :名無しさん@お腹いっぱい。2011/07/09(土) 11:33:19.65
一応findがない環境を想定して、findを使わない例。

function findd() {
  for D in "$1"/*; do
    if [ -d "$D" ]; then
      echo "$D"
      findd "$D"
    fi
  done
}
findd dir

dir以下に存在するディレクトリを表示。シェルスクリプトでゴリ押し。
ネットのどっかにチュートリアルなかったっけ。それじゃ足りないかい?
38 :名無しさん@お腹いっぱい。2011/07/09(土) 16:10:16.06
>>35
.(ドット)で始まるディレクトリを取りこぼすな、これ
39 :名無しさん@お腹いっぱい。2011/07/09(土) 16:26:21.56
>>38
もし必要なら事前に次を実行しとけばどうさ?
$ shopt -s dotglob

ディレクトリにはハードリンクできなかったと思うけど、ループしてても動くのかね?findは(確か)止まるが。
ま、元の質問はZIPを展開したものに対してだから、気にしなくていいって言えばいいのか。
40 :名無しさん@お腹いっぱい。2011/07/09(土) 16:56:42.99
>>35
-n という名前のディレクトリが有ったら表示されない。
41 :名無しさん@お腹いっぱい。2011/07/09(土) 17:07:20.26
>>40
それは無いだろ?必ず一番初めに関数に渡したディレクトリ名が頭に付くんだから。
42 :名無しさん@お腹いっぱい。2011/07/09(土) 17:08:28.95
>>40
いや、"$1"/* から開始してるから
-n があっても hoge/-n になるから、問題ないだろ。
44 :名無しさん@お腹いっぱい。2011/07/12(火) 19:40:46.08
centos5で質問です
↓のようなテキストファイルがあります

1 a.log root
2 a b.log apache
3 c.log mysql

ここでlogファイル名だけを抜き出したいのですが良い方法は無いでしょうか?

awk等で列を抜きだそうとすると間にスペースが入っている為、どうしても2行目がb.logと抜き出されてしまいます。
45 :名無しさん@お腹いっぱい。2011/07/12(火) 19:44:55.52
二行目は"a b.log"ってことなのか?
最後の単語には空白が含まれない前提で、
awk '{ $1 = ""; $NF = ""; print $0 }' | sed -e 's/^ //' -e 's/ $//'
46 :名無しさん@お腹いっぱい。2011/07/12(火) 19:51:42.21
>>45
>二行目は"a b.log"ってことなのか?
その通りです。
正確にはスペースが複数入っているようなファイル名を想定してますが…

出先で直ぐには確認出来ませんが試して見ます。
47 :名無しさん@お腹いっぱい。2011/07/12(火) 20:02:14.49
>>44 >>45
sedだけで出来る

sed 's/[^ ]* //; s/ [^ ]*$//'
48 :名無しさん@お腹いっぱい。2011/07/12(火) 20:28:22.50
>>47
それを書くなら、
sed 's/[^ ]* *//; s/ [^ ]*$//'
だろ。
49 :名無しさん@お腹いっぱい。2011/07/12(火) 20:51:25.57
>>48
それだと " a b.log" (頭にスペース)のファイル名が正しく取り出せないだろw

まあ、元の仕様が不明だから何とも言えないが。
50 :名無しさん@お腹いっぱい。2011/07/12(火) 23:52:50.07
>>46
65 :名無しさん@お腹いっぱい。2011/07/14(木) 03:46:47.41
>>44
1,2,3 が最初のフィールドで、root,apache,mysql が最後のフィールドで
間にあるのがログファイルのリストだと仮定するならば、awkコードを

{
for(n=2; n<NF; n++) {
printf "%s ", $n
}
print ""
}

とすれば出来るんじゃないかな
ただ間にあるログファイル名が「空白自体をファイル名に含む」という場合はこれではできない。
>>49 の言う通り、そういう細かい仕様を明確にしないと書きようがない。
51 :名無しさん@お腹いっぱい。2011/07/13(水) 14:24:43.76
誰かわかる方、今週中にお願いします。

以下のバッシュをボーンで書き直せ

#!/bin/bash

color=(Red Green Blue)

for ((i = 0; i < 10; i++)) {
echo ${color[RANDOM*3/32768]}
}
57 :名無しさん@お腹いっぱい。2011/07/13(水) 18:30:19.64
>>51
わりぃ、わりぃ。直ぐに書けたけど、環境が分からなくてね。今bourne動かせるかい?
64 :名無しさん@お腹いっぱい。2011/07/14(木) 01:23:51.41
>>51
#!/bin/sh

color=(Red Green Blue)

for ((i = 0; i < 10; i++)) {
echo ${color[RANDOM*3/32768]}
}
52 :512011/07/13(水) 16:59:52.85
早くしろ、おせーぞ
金曜の朝までだ。最低でも月曜の朝まで
俺の単位が掛かっている
55 :名無しさん@お腹いっぱい。2011/07/13(水) 17:23:02.47
単位がかかってるのかしょうがないな。特別にやってやろう。

#!/bin/sh

exec /bin/bash <<'EOF'
color=(Red Green Blue)

for ((i = 0; i < 10; i++)) {
echo ${color[RANDOM*3/32768]}
}
EOF
62 :512011/07/13(水) 21:05:23.15
みなさん多数の回答ありがとうございました。
一番回答が早かった >>55 さんので提出しようと思います。
本当に助かりました。
80 :名無しさん@お腹いっぱい。2011/07/15(金) 23:04:20.09
おまえは>>55 から何も学ばなかったのか?
56 :512011/07/13(水) 17:30:42.13
なんで返事がないのですか?
原理とかも質問したいので、できるだけ早くお願いします。
58 :名無しさん@お腹いっぱい。2011/07/13(水) 18:34:13.92
オマエラ不親切だな。ちゃんと教えてやれよ。


#/bin/sh

echo '#include <time.h>
#include <stdlib.h>
#include <stdio.h>
char*c[]={"Red","Green","Blue"};
int main(){int i;srand(time(0));for(i=0;i<10;i++){
puts(c[rand()*3LL/((RAND_MAX+1LL))]);}return 0;}
'>t.c;gcc t.c;./a.out;rm a.out
63 :名無しさん@お腹いっぱい。2011/07/13(水) 22:39:12.85
#!/bin/sh
str_rand=
str_rand_buf=
while : ; do
 str_rand=$( expr "`echo "$$$str_rand$( date )" | md5sum`" : '\([^ ]*\)' )
 str_rand_buf=$str_rand_buf$str_rand
 if expr $str_rand_buf : '^\(...\)*$' >/dev/null ; then
  echo $str_rand_buf | sed 's/.../\0\n/g'
  str_rand_buf=
 fi
done | tr 0123456789acf 'bureRGdlRlrGu' |
sed -n 'y/b/B/;/Red/p;/Gre/s/$/en/p;/Blu/s/$/e/p' |
head -n 10

理解度の違いを見せ付けるチャンス!
67 :名無しさん@お腹いっぱい。2011/07/14(木) 07:30:57.51
bashって do 〜 done を { 〜 } で書けたんだね。知らなかった。
manにない(のかな?)けど、bashの拡張?何時ごろ入ったんだろ。
68 :名無しさん@お腹いっぱい。2011/07/14(木) 07:40:43.45
>>67
ボーンでも for で { } って書けるよ。昔から。
whileでは書けない。
69 :名無しさん@お腹いっぱい。2011/07/14(木) 07:53:05.71
>>68
そーなのかー。ありがとう。確かにwhileは無理だった。でもselectはいけた。
whileはlistをとるから、区別できなくて使えないんだろうね。
while :;:;:;:;:;:;:; do echo ok; done
こんな風に書けるとは思ってなかったよ。
70 :名無しさん@お腹いっぱい。2011/07/15(金) 12:07:24.41
>>262
ファイルの先頭に文字を追加するにはどうすればいいですか?
73 :名無しさん@お腹いっぱい。2011/07/15(金) 12:45:53.46
>>70
rename "" "prefix" file...
とか
prename 's/^/prefix/' file...
とか
74 :名無しさん@お腹いっぱい。2011/07/15(金) 13:01:11.76
>>73
ありがとうございます。

Sedでファイル先頭を置換するのと、
中カッコでエコーとキャットをグルーピングする方法を思いついたので、今回はそれで行こうと思います。
75 :名無しさん@お腹いっぱい。2011/07/15(金) 13:16:40.99
>>74 を見る限り、
>>73 は明らかに勘違いした回答(ファイル名を変換してるw)だが、
ありがたいか?w
76 :名無しさん@お腹いっぱい。2011/07/15(金) 13:27:40.84
>>74の書き方はネタのつもりでしょ。
77 :名無しさん@お腹いっぱい。2011/07/15(金) 14:34:55.66
>>73
横からだが、ありがとう。renameの亜種がいっぱいあるせいでperlで実装されたものが行方不明だったんだが、
うちのシステムにもprenameで見つかった。プログラムの名前はかち合うように作らないで欲しいな。
71 :名無しさん@お腹いっぱい。2011/07/15(金) 12:31:53.02
スレが建ってからおよそ一ヶ月。回答を得られるのは約四ヵ月後か。
72 :名無しさん@お腹いっぱい。2011/07/15(金) 12:34:06.01
ずいぶんロングパスだね。>>262までは2か月くらいかなあ。
78 :名無しさん@お腹いっぱい。2011/07/15(金) 15:12:27.61
>プログラムの名前はかち合うように作らないで欲しいな。

*BSD や Linux の killall と同じつもりで Solaris で killall を叩いてしまうと、
プロセスだけでなく自分まで死にたくなるな。
# Solaris の killall の方が先のはず
79 :名無しさん@お腹いっぱい。2011/07/15(金) 18:50:08.88
以下のバッシュをボーンで書き直せ
ただし、添付ファイルを使わないこと

わかる方、来週中までにお願いします。

#/bin/bash

diff -c <(ls -l /フォルダ1) <(ls -l /フォルダ2)
129 :名無しさん@お腹いっぱい。2011/07/18(月) 20:38:06.07
>>79 わかる方、今週中にお願いします
130 :名無しさん@お腹いっぱい。2011/07/18(月) 21:53:30.40
>>129
コテハンつけてくれないかな。
182 :名無しさん@お腹いっぱい。2011/07/24(日) 23:10:11.58
>>79 早く、明日の朝までにお願いします!!
184 :名無しさん@お腹いっぱい。2011/07/24(日) 23:47:31.61
>>79

dir1=`ls -l /dir1`
dir2=`ls -l /dir2`
diff -c "$dir1" "$dir2"
186 :名無しさん@お腹いっぱい。2011/07/25(月) 04:05:42.24
>>79

#! /bin/sh
ls -l /フォルダ1 | (ls -l /フォルダ2 | diff -c /dev/fd/3 /dev/fd/4 4<&0) 3<&0
187 :名無しさん@お腹いっぱい。2011/07/25(月) 06:30:34.66
>>186
ありがとうございます。これで提出しておきます。
82 :名無しさん@お腹いっぱい。2011/07/16(土) 01:18:33.17
bashとかだと$RANDOMで乱数得られるけど、他のやり方ってどんなのがある?
odとかで/dev/urandom読むとか、md5sumみたいなハッシュ関数使うとか出てるけど。

自分はあまり精度が必要でないときdateでナノ秒とってきて使ったことはある。
awkのrand()使うのも思いついたけど、これだと何でもありか。

環境に依存しないのは、exprで線形合同法でも実装するくらいしかないのかな?
83 :名無しさん@お腹いっぱい。2011/07/16(土) 05:56:58.17
ぶっちゃけawk使ったほうが環境依存度としては低いかも知れないw(awkにしか依存しないことになるので)
シェルスクリプトとしては/dev/randomをodで読む、が一番いい気がするんだけどなあ
84 :名無しさん@お腹いっぱい。2011/07/16(土) 07:41:17.60
/dev/randomってどのシステムにもあるの?仕様も同じ?つか、うちだと止まるんだけど。
85 :名無しさん@お腹いっぱい。2011/07/16(土) 07:44:35.06
gawkやnawkではrand()が使えるが、純正awk(solarisのawkとか)では
rand()は使えないので、その場合わけが必要になる。
87 :名無しさん@お腹いっぱい。2011/07/16(土) 07:59:53.03
randomはともかく、urandomってどの環境にでもあるものなのか?

>>85
そうなのか…perlとかのが却っていいのかな?
94 :名無しさん@お腹いっぱい。2011/07/16(土) 09:15:14.63
>>85
POSIXならrand()あるんだからそれくらい実装してくれよ。
86 :名無しさん@お腹いっぱい。2011/07/16(土) 07:56:05.57
/dev/randomは乱数のタネがたまるまでブロックする。
つーか、貴重な共有リソースだから素人は使うな。/dev/urandom使え。
88 :名無しさん@お腹いっぱい。2011/07/16(土) 08:20:01.28
>>86
/dev/urandom -> random に symlinkされてる FreeBSDでどうしろと?
90 :名無しさん@お腹いっぱい。2011/07/16(土) 08:49:18.46
FreeBSDはデフォルトが/dev/urandomのように振る舞うようになっている。
バカが理解せずに使うからバカ用のインターフェースが残された。
91 :名無しさん@お腹いっぱい。2011/07/16(土) 08:59:56.03
んで、urandomはどの環境にも必ずあるの?
そもそも環境依存の話をしてるんだから、問題はそこだと思うのだけど。
96 :名無しさん@お腹いっぱい。2011/07/16(土) 13:48:43.12
どのシステムにも漏れなく入っているハッシュを計算するコマンドで代用はどう?
「どのシステムにも」って所が難しいか。
98 :名無しさん@お腹いっぱい。2011/07/16(土) 15:23:25.28
rand() {
  _seed_="`expr \( ${_seed_} \* 1103515245 + 12345 \) % 4294967296`"
  expr ${_seed_} / 65536 % 32768
}
exprだけで実装。man randからパクリ。

$ _seed_=$$; for i in `seq 5`; do rand; done
21733
22089
6602
23744
28678
乱…数…?か?exprって幾つまで数えられたっけ?そもそも種はどこから持ってくるべきなんだ?
100 :名無しさん@お腹いっぱい。2011/07/16(土) 19:42:26.34
>>98
その rand()関数、単純に randで呼び出して表示するだけならいいけど、

i=`rand`
echo $i
みたいに変数に代入する使い方をすると
rand関数全体が暗黙のサブシェルになって、_seed_が更新されないという罠。
101 :名無しさん@お腹いっぱい。2011/07/16(土) 20:07:11.61
環境に依存しない、現在時刻を数値で取得する方法ってあったっけ。dateで出来たか?

>>100
マジだな。そこまで気にしてなかったわ。欲しい乱数の個数が決まってるなら、これでどうだろ。
for RND in $(for in `seq 10`; do rand; done`); do 〜 done
99 :名無しさん@お腹いっぱい。2011/07/16(土) 19:04:38.58
乱数の種の定番は現在日時じゃね
103 :名無しさん@お腹いっぱい。2011/07/17(日) 10:13:28.52
>>99
まだこんな馬鹿がいるのか
102 :名無しさん@お腹いっぱい。2011/07/16(土) 23:25:02.38
mktemp -u XXXXXX
で何とかならないか。A-Za-zが邪魔だけど。cygwinだと/dev/urandomとか
ないんだけど、mktempもGNUにしかない?
124 :名無しさん@お腹いっぱい。2011/07/18(月) 14:18:10.71
>>102
-uオプションって初めから有った?昔mktempスクリプトから
使おうとして動かなかったことがあったけど、何が原因だったけ…

もう一つ思いついたのは、重複が無いって条件付でこんなのはどうだ?
seq 1 10 | sort -R
125 :名無しさん@お腹いっぱい。2011/07/18(月) 14:31:10.36
>>124
sortの -Rオプションが思いっきりGNUですw

GNU mktemp -u はドライラン
freebsdやsolarisの mktemp -u は、unlinkオプション。
動作が違う。
126 :名無しさん@お腹いっぱい。2011/07/18(月) 14:49:59.58
>>125
やっぱりかー。微かにそんな気はしてたToT
mktempとか(自分のまわりでは)良く使われてるのに
別の環境に持ってくと挙動が違って泣きたくなる事あるよね。

こんなオプションが挙動違うのかよって思ったコマンドってどんなのがあったけかな…
104 :名無しさん@お腹いっぱい。2011/07/17(日) 10:23:13.19
もうjotでいいやw
105 :名無しさん@お腹いっぱい。2011/07/17(日) 10:45:34.78
>>103
じゃーどうすりゃいいのよ?

>>104
これってBSDだけ?わざわざ用意するってことは、他に適当な方法がないのだろうね。
107 :名無しさん@お腹いっぱい。2011/07/17(日) 17:33:07.68
暗号にもちいるなら予測可能なタイムスタンプは使わない。
シミュレーションなどで再現性が重要な場合もタイムスタンプは使わない。
したがって、タイムスタンプ使うバカは死滅すべしが結論。
108 :名無しさん@お腹いっぱい。2011/07/18(月) 00:28:21.96
大量データを処理するツールを作っているのですが、
bash/perl/awkどの言語で作成するべきか悩んでいます。
言語の特性を考えると、どれが一番おすすめでしょうか?

作成するツールの要件は下記の通り。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
作業前後でOSすべてのファイルリスト+md5sumを取得、
比較を取得し、差分を検出する。

取得するファイルリストはfind / -printf %p %T+ %l %s %m %g %uで、
%pの結果すべてをmd5sumに喰わせてハッシュ値を取得する。
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
最初はbashで作成したのですが、思ったような性能を出すことができませんでした。
高速化を目指しAwkで作成したところ、10分の1以下になりました。
perlならもう少し早くなります。

が、チームにperl/awkが使えるメンバが自分以外不在です。
bashなら多少使えるそうなのですが…。

個人的には、bashが使えればawkも似たようなものなので、awkで作成しようかと思っているのですが。
121 :名無しさん@お腹いっぱい。2011/07/18(月) 12:13:32.54
>>108
tripwireというファイルの改変を検出するツールがある。
122 :名無しさん@お腹いっぱい。2011/07/18(月) 12:17:22.58
>>121
tripwireも検討したのですが、処理が重く…
時間がかかるため、自作することにしております。
128 :名無しさん@お腹いっぱい。2011/07/18(月) 17:15:36.05
>>108
自己レスです。
教えていただいた方法で大分早くできました。

find の結果をawkで1行ずつ整形。
ディレクトリ、シンボリックリンクなら%p %T+ %l %s %m %g %uのみ出力。
ファイルだったらxargs -P 0 md5sum にてハッシュ値を取得、
findでとった%p %T+ %l %s %m %g %uにハッシュ値を付与しました。

大分早くはなりましたが、勉強も兼ねてもう少し、うまい方法がないか考えてみます。
109 :名無しさん@お腹いっぱい。2011/07/18(月) 00:55:51.19
パフォーマンスを向上させたいならホットスポットを見つけて、地道に対処するべきなんじゃないの?
原因も分からず場当たり的に作業しても何も残らんよ。
110 :名無しさん@お腹いっぱい。2011/07/18(月) 01:11:53.63
>>109
ネックになってるのはハッシュ値を計算している箇所です。
bashだと一行ずつmd5sumを呼び出すためプロセス起動、
ハッシュ値計算とコストがかかりすぎます。

代案としてawk,perlならそこを解決できるとわかったのですが。

ですので、bashでここの問題を解決できるならbashでも構いません。
例えばファイルを一意に識別するのにmd5sum以外の方法があったりとか。
114 :名無しさん@お腹いっぱい。2011/07/18(月) 01:34:24.76
>>110
awk, perl ではハッシュ計算を行っていないということですか?
116 :名無しさん@お腹いっぱい。2011/07/18(月) 01:40:57.89
>>114
いえ、しています。
が、findの結果一行ごとにmd5sumを起動しないので、早くなっていました。
111 :名無しさん@お腹いっぱい。2011/07/18(月) 01:24:02.13
xargs使って複数のパスを同時に引数に渡せよ。
112 :名無しさん@お腹いっぱい。2011/07/18(月) 01:25:25.53
>>111
ありがとうございます。
ためしてみます。
113 :名無しさん@お腹いっぱい。2011/07/18(月) 01:25:50.09
それから内容の同一性確かめなくてもst_ctime使えばいいんじゃないの?
それならrsyncのdry run。
115 :名無しさん@お腹いっぱい。2011/07/18(月) 01:39:49.47
>>113
ls -lで確認できる権限、パーミッション、オーナー、タイムスタンプ、ファイルサイズが全く同じで、
中身だけ異なるようなファイルを cp -pで入れ替えられた場合を考慮していたつもりだったのですが。
今ctimeの仕様を見るとinodeも考慮してくれているのですね。
であれば、ctimeでOKという気もします。
rsyncのdry-runというのもあるのですね…
勉強不足でした。
まだ理解で規定な箇所もありますが、
早速、教えてもらった方法を試してみます。
ありがとうございます。
118 :名無しさん@お腹いっぱい。2011/07/18(月) 10:12:13.56
>>113
st_ctimeでは無理でした。

事前、事後にrsyncでバックアップ、リストアを実施しています。
リストアップのタイミングで必ずctimeが変わるため、
ファイルの内容に変更がない場合でも必ず差分として出てしまいます。
代わりにmtimeが戻るのでmtimeで比較も考えたのですが、
touch コマンド等で修正時刻を操作された時に検知が出来ません。

やっぱり、なにかしらファイルの同一性を見る必要があります。
xargsは文字数制限が発生したおちましたが、
オプションでなんとかならないか調べてみます。
117 :名無しさん@お腹いっぱい。2011/07/18(月) 06:21:49.95
rsyncの--checksumオプションを使った場合、
awkやperlと比べてどちらが速いのだろうかと思った。
119 :名無しさん@お腹いっぱい。2011/07/18(月) 10:13:09.33
>>117
私が作るアホシェルよりは早いきがしますね。
こちらも試してみます。
ありがとうございます。
120 :名無しさん@お腹いっぱい。2011/07/18(月) 12:02:10.50
ノンストップの処理を行わせておいて、指定した時間の経過で自爆させる時って
( cat /dev/zero > /dev/null & ; sleep 10 ; kill $$ ) &
のような感じで良いですか?
123 :名無しさん@お腹いっぱい。2011/07/18(月) 14:08:26.48
>>120
$$はサブシェルのPIDに展開されない。親が死ぬよ。

ファイルシステム全体のスナップショットを取って、そこから個々のファイルの差分を取れたら凄く楽そうなんだがなぁー。
131 :名無しさん@お腹いっぱい。2011/07/18(月) 23:45:41.77
シェルスクリプトで、特定の確率でcommandを実行する方法ありますか?
単純に 30% とかなら
RANDOM % 3 -eq 0
でいけると思いますが、27% とかだったらどうすればいいのか。。。
132 :名無しさん@お腹いっぱい。2011/07/19(火) 01:11:18.64
>>131
function foo() {
local -i i="$1"
((RANDOM % 100 < i)) && "$2"
}

foo 27 command

とかで正しい?
133 :名無しさん@お腹いっぱい。2011/07/19(火) 16:45:00.33
>>132
すみません、頭が固くて嫌になるのですが
RANDOM % 100 < i
これでどうして確率になるのでしょうか?
135 :1322011/07/19(火) 17:47:19.49
>>132 は
RANDOM の取り得る値が 0 から 32767 だから、
foo 27 command
だと正確には 27% にならないかな。

RANDOM % 3 -eq 0 で 30% らしいから、そこまで正確でなくて良いのか。
136 :名無しさん@お腹いっぱい。2011/07/19(火) 17:47:38.63
>>131
RANDOM % 3 -eq 0
は、30%じゃなくて 33.3333..% な。

あと、算術式だと ((RANDOM % 3 == 0)) な。
138 :名無しさん@お腹いっぱい。2011/07/19(火) 20:36:23.78
>>133
bashだから
137 :名無しさん@お腹いっぱい。2011/07/19(火) 17:55:14.67
%単位で正確にやるには100の倍数からはみ出たところを捨てるか。

while (((i = RANDOM) >= 32700)); do :; done
((i % 100 < 27)) && echo OK
141 :名無しさん@お腹いっぱい。2011/07/20(水) 13:15:05.19
>>140
ちがうよ。

>>137 で合ってるよw
139 :1312011/07/20(水) 11:03:58.02
みなさま、ありがとうございました。
理解できました。

それほど正確じゃなくてもいいので、これで十分です。ありがとう
140 :名無しさん@お腹いっぱい。2011/07/20(水) 13:07:21.50
>>173
RANDOM >= 32700 じゃなくて RANDOM <= 32700
だな
142 :名無しさん@お腹いっぱい。2011/07/20(水) 13:20:05.99
>>140
こういう、正解を間違い呼ばわりするアホは何とかならないものか
156 :名無しさん@お腹いっぱい。2011/07/21(木) 21:15:13.59
>>140もあれだが、おまえももっとさわやかになれよ
143 :1402011/07/20(水) 14:49:05.40
なんで?

while (((i = RANDOM) >= 32700)); do :; done

これだと i は 32700〜32767

((i % 100 < 27)) → (0〜67 < 27)

おかしいじゃん。

144 :名無しさん@お腹いっぱい。2011/07/20(水) 14:59:57.76
>>143

> これだと i は 32700〜32767

↑ ハイ、ここ違うね。

おまえ数学もプログラムも苦手だろw
145 :名無しさん@お腹いっぱい。2011/07/20(水) 15:08:47.98
>>143
while (((i = RANDOM) >= 32700)); do :; done
の実行後、
iの範囲は 0〜32699 になる。

whileループの基本。
わからないなら試してみろ。

$ while (((i = RANDOM) >= 32700)); do :; done
$ echo $i
25678
153 :名無しさん@お腹いっぱい。2011/07/20(水) 19:10:37.88
それよりアホな子の >>140 = >>143 の釈明会見まだぁ?
155 :名無しさん@お腹いっぱい。2011/07/21(木) 20:52:45.10
>>140 = >>143 は赤面して逃げ出したのか?
146 :名無しさん@お腹いっぱい。2011/07/20(水) 16:24:25.04
このやりかたって、乱数が完璧なら、
一定の確率で1日たっても終わらんなんて事態も発生するよな
147 :名無しさん@お腹いっぱい。2011/07/20(水) 17:30:48.35
たしかに可能性はゼロではないが、
1日どころか1秒以上ループが回り続ける確率ですら
宝くじで3億円当てるより低いだろう。
148 :名無しさん@お腹いっぱい。2011/07/20(水) 18:17:25.23
それを気にするなら、unsetとかexportとか気にするべきでは?
どっかにexport RANDOM=40000とか入れられたら意図的に無限ループにできる。
150 :名無しさん@お腹いっぱい。2011/07/20(水) 18:27:10.90
>>148
export RANDOM=40000
ってやっても、それはseedが設定されるだけで
RANDOMは乱数のまま(無限ループにならない)。

一旦unset RANDOMしてからexport RANDOM=40000とやれば
RANDOM=40000固定になるが、いくらexportしても
スクリプト起動時に別のシェルが起動され、
exportに関わらずRANDOMは乱数機能で動作する。
152 :名無しさん@お腹いっぱい。2011/07/20(水) 18:56:13.45
>>151
>exportするとそこから呼ばれたスクリプトの乱数列が固定
>>150のいうseedの意味が分からんかったのか。
ランダムなseedを保証したかったら、スクリプトの中で
RAMDAMをランダムな数値でexportすればよい
154 :名無しさん@お腹いっぱい。2011/07/20(水) 19:29:27.84
>>152
RANDOMをランダムな数値でexport…だと…?
151 :名無しさん@お腹いっぱい。2011/07/20(水) 18:42:44.54
確かに固定にしようと思ったらunsetやってからexportしないと駄目だね。
だけど、それでスクリプト書いて試したらRANDOMが40000で固定されたんだが?うちのbashだけか?

もう一つ気が付いたのだが、exportするとそこから呼ばれたスクリプトの乱数列が固定される。
用途によってはこれも問題な気がする。
157 :名無しさん@お腹いっぱい。2011/07/23(土) 14:32:26.17
他のサーバにtelnetでログインして、シェルを実行して、ログを取得することはできますか?
158 :名無しさん@お腹いっぱい。2011/07/23(土) 14:58:56.53
できますん。
そもそもtelnetじゃないとだめなのか?
普通そういう時にはremshやsshを使うもんだが。
160 :名無しさん@お腹いっぱい。2011/07/23(土) 15:27:00.01
>>158、159
ありがとうございます。
remshというのは知りませんでした。
sshは使えないと思います。
expectはネットで用例を見つけました。
teratermマクロで似たようなことをやっていたこともあるんですが、シェルスクリプトにした方が色々出来そうなのでちょっと調べてみます。
161 :名無しさん@お腹いっぱい。2011/07/24(日) 01:22:52.02
>>160
> sshは使えないと思います。

使えるよ。ssh-agent使えよ。
162 :名無しさん@お腹いっぱい。2011/07/24(日) 03:10:34.27
>>161
該当のサーバはtelnet接続のみでssh接続自体ができないということです。
設定を変える権限もありませんので。
163 :名無しさん@お腹いっぱい。2011/07/24(日) 05:01:00.56
ログの出力先がサーバでなく、ターミナルを動かしてるPC側ってことなら
ターミナルソフトによってはログ取れるのもあるから(teratermも確かあるよね?)
ターミナルでログ開始して、ログ取りたいコマンド打てば良いんでね
164 :名無しさん@お腹いっぱい。2011/07/24(日) 12:17:28.79
>>163
teratermでは出来ると思いますが、バージョンによってマクロの仕様が異なるのと、フリーソフトに頼るのもいまいち不安なのです。
expectで各サーバにログインして、シェルスクリプトを実行、ログをサーバ上に保存。ftpでログを接続元サーバにget。
取得したログをcatで一つにまとめる。
こんな感じで考えています。
自宅でvmware playerでcent osとfreeBSDを動かせるようにしているので、それで試してみようと思います。
しかし、cent osはsshでしか接続出来なかったとおもうので、設定を弄らなければならないですね。
165 :名無しさん@お腹いっぱい。2011/07/24(日) 12:36:39.42
わざわざ別ファイルに保存して、FTPで取りに行くようにするのはなんでだろ?
178 :名無しさん@お腹いっぱい。2011/07/24(日) 16:31:56.55
>>165
expectで接続元のサーバにリダイレクト出来ますか?
200 :名無しさん@お腹いっぱい。2011/07/25(月) 11:45:49.19
>>178
ログはstdoutに出して、その出力を全部expectで処理すればいい。
expectに付いてくるサンプル改造すればすぐ出来る。
166 :名無しさん@お腹いっぱい。2011/07/24(日) 14:19:06.63
凄い初歩的な質問で申し訳ないのですが、2個以上の半角スペースを区切り文字に指定して抜き出す方法ってありますか?

例えば
a b c d e

の場合c dだけ抜き出したいんですが…
168 :名無しさん@お腹いっぱい。2011/07/24(日) 14:23:14.34
>>166
あう…例えが全部半角になっちゃった

_が半角スペースで
a__b___c_d__e
の場合です。
170 :名無しさん@お腹いっぱい。2011/07/24(日) 14:37:19.49
>>166

sed 's/.*[ ][ ]¥(.*¥)[ ][ ].*/¥1/'
173 :名無しさん@お腹いっぱい。2011/07/24(日) 14:52:42.92
>>170
おー素晴らしい。
ありがとうございます。
167 :名無しさん@お腹いっぱい。2011/07/24(日) 14:23:03.91
awk '{ print $3,$4 }'
169 :名無しさん@お腹いっぱい。2011/07/24(日) 14:26:05.14
>>167
うーん
言い方が悪かったですね。
c_dの部分は一列として抜き出したいです

この場合は3列目だけでc_dって感じで…
171 :名無しさん@お腹いっぱい。2011/07/24(日) 14:46:48.40
>>169
>>167でちゃんと一列で出てくると思うけど。
172 :名無しさん@お腹いっぱい。2011/07/24(日) 14:47:27.51
あ、行じゃなく列ってことか?
いまいち仕様がよくわからん。
174 :名無しさん@お腹いっぱい。2011/07/24(日) 14:59:17.68
>>172
$3 $4だと冒頭とかがa_bみたいな文字列だった場合、ずれてしまうんです…でもありがとう。
176 :名無しさん@お腹いっぱい。2011/07/24(日) 15:01:41.19
>>174
冒頭が「a b」でもちゃんと出るでしょ?
177 :名無しさん@お腹いっぱい。2011/07/24(日) 15:08:27.16
>>176
えーと
こんな時は…
a_b___b__c_d__e

bcって出ちゃうと思います。
こんな時でもc_dって出したいわけです。
179 :名無しさん@お腹いっぱい。2011/07/24(日) 19:26:16.15
>>177
なんか凄い出遅れた感があるけど、awkでやるならフィールドセパレータに正規表現を使えばいい。
awk -F'__+' '{print$3}'
同じようにアンダースコアはスペースに置き換えてね。
180 :名無しさん@お腹いっぱい。2011/07/24(日) 20:22:08.50
>>179
ほーawkでフィールドセパレート指定出来るのは知ってましたがそんなやり方有るんですね
勉強になります。
見た目はそっちのがスマートですね。
181 :名無しさん@お腹いっぱい。2011/07/24(日) 21:05:20.05
>>179
いま帰って試して見たんですがawkのやり方だと完璧ですね。
上で教えていただいたsedでやる方法だと文字が長くなったりスペースの数が不定だと変な所が抜き出されて駄目っぽいです。
今回はこちらの方法で行きますTHX
188 :名無しさん@お腹いっぱい。2011/07/25(月) 10:30:54.08
文字列を一文字ごとにバラバラに処理するのは、どう書くのが一番かな?
できるだけ多くのシェルで動かせるようにしたいのだけど。
自分で思いついたのはこんな感じ。
while read line; do
while :; do
chr=`echo -n "$line" |cut -c 1`
echo -n "<$chr>"
[ "$chr" = "$line" ] && break
line="$(echo -n "$line" |cut -c 2-)"
done
echo
done
191 :名無しさん@お腹いっぱい。2011/07/25(月) 10:56:15.33
bashならこうも書けるか。部分文字列の置換って標準的かな?
while read line; do
while [ -n "$line" ]; do
chr="${line:0:1}"
echo -n "<$chr>"
line="${line:1}"
done
echo
done

>>188
これのchrに設定するところ、"〜"で括り忘れてた。
192 :名無しさん@お腹いっぱい。2011/07/25(月) 11:05:34.59
>>191
bash使っていいならもっと簡単に書ける。
(改行も同列扱いだけど)


while read -n 1 c
do
echo -n "<$c>"
done
194 :名無しさん@お腹いっぱい。2011/07/25(月) 11:17:25.34
>>193
欲嫁。

>>191
> bashならこうも書けるか。

に反応してるんだろ。
「どうせbashならもっと簡単に書け」と。
195 :名無しさん@お腹いっぱい。2011/07/25(月) 11:20:11.07
>>193
そう突っかかるなよ。>>188は「できれば」って言ってるし答えてる方も
『bash「なら」』って書いてるだろ
199 :名無しさん@お腹いっぱい。2011/07/25(月) 11:37:42.92
>>194
はあ? ↓これをまとめて書いたんだが。池沼?

if (181 == 191) {
> できるだけ多くのシェルで動かせるようにしたいのだけど。
って、お題出してといてbashならって言い出すってなんなの? 池沼?
} else {
> できるだけ多くのシェルで動かせるようにしたいのだけど。
って、お題もらっといてbashならって言い出すってなんなの? 池沼?
}
201 :名無しさん@お腹いっぱい。2011/07/25(月) 11:47:15.57
>>199
ちょっと意味がわからない。
205 :名無しさん@お腹いっぱい。2011/07/25(月) 12:02:42.08
>>199
私の書き方が悪く、意味が不明瞭になってしまったようで、大変申し訳なく思っています。
そこは、bashではこう書けるが他のシェルでも使える標準的な方法か?と聞きたかったのです。
重ね重ね、池沼さん、大変申し訳ありませんでした。
189 :名無しさん@お腹いっぱい。2011/07/25(月) 10:32:20.19
そういうのはLL使っちゃうな。
196 :名無しさん@お腹いっぱい。2011/07/25(月) 11:22:06.95
>>189
> できるだけ多くのシェルで動かせるようにしたいのだけど。
ってお題なのに、LL使っちゃうって言い出すのってなんなの? 池沼?
197 :1892011/07/25(月) 11:29:21.25
>>196
「できるだけ多くのシェルで動かせるようにしたい」ってだけで、
「シェルで動かなければならない」ってことではないでしょ?
193 :名無しさん@お腹いっぱい。2011/07/25(月) 11:12:55.14
> できるだけ多くのシェルで動かせるようにしたいのだけど。
ってお題なのに、bashならって言い出すのってなんなの? 池沼?
202 :名無しさん@お腹いっぱい。2011/07/25(月) 11:51:29.37
>>193は脊髄反射系
198 :1892011/07/25(月) 11:30:37.16
要件をちゃんとわかってるのは質問者だけなんだから、
質問者以外がどうこう言ってもしょうがないよ。
203 :名無しさん@お腹いっぱい。2011/07/25(月) 11:54:58.50
188です。いろいろなレスありがとう御座います。
シェルスクリプトで簡単なパーサを書きたいなと思いまして、質問しました。
perlのようなLLや、sed、awkなどを使うと全部それにやらせればいい
と言う話になりますので、私自身は使わずに書きました。

実際書こうとすると、個々の文字に分解する標準的な方法が無いのかと気になった次第です。
せめて簡単な正規表現をシェルスクリプトだけで実装したいので、
正規表現を扱える外部コマンドを呼ぶのは何だかな、と言ったところです。
215 :名無しさん@お腹いっぱい。2011/07/25(月) 17:08:09.74
>>203
shは構文木を保持するのが苦手。

カーニハンが"Beautiful code"で書いた
正規表現関数を模倣してみては? 文書はPDFで手に入る。
あれは内部表現使わずに解析する毎に逐次的に実行してるから。
217 :名無しさん@お腹いっぱい。2011/07/26(火) 09:10:17.00
>>215
ありがとう。元々内部表現を使う実装は無理かなと思っていたので、そのようにするつもりです。
どちらにせよ、一文字一文字個別に扱えたほうが都合が良いので、どのような方法があるのだろうと思ったのです。
204 :名無しさん@お腹いっぱい。2011/07/25(月) 11:56:29.84
全部それにやらせればいいのに。
だめなのかな。
206 :名無しさん@お腹いっぱい。2011/07/25(月) 12:06:30.43
>>204
同じような実装をしたときにどの程度の速度差があるのか調べる目的もあります。
シェルスクリプトは基本的に速さに期待できないのは分かっていますが、計ったことがなかったもので。
207 :名無しさん@お腹いっぱい。2011/07/25(月) 14:39:53.04
アンチbashがよく可搬性の点から、bashスクリプトを非難するけど、
シェルのシェアを考えると、bashはどの程度なんだろうね。
MacOSXやLinuxが基本bash (dashを含む)なので、bashが首位で
かなりの割合を占めそうだけど。
208 :名無しさん@お腹いっぱい。2011/07/25(月) 14:42:56.49
世界全体のシェアを考えてもあんまり意味がないと思うなぁ。
要は自分が作ったスクリプトが自分が使う環境で動けばいいんでしょ。
209 :名無しさん@お腹いっぱい。2011/07/25(月) 14:46:19.02
bashスクリプトが#!/bin/shを名乗ってるから非難するのであって
#!/bin/bashなら問題ないよ
210 :名無しさん@お腹いっぱい。2011/07/25(月) 15:08:47.23
Linuxでは sh -> bashのシンボリックリンクによって
shの正体はbashであることを明示している。(Debianは sh -> dash)

しかし、FreeBSDはshの正体がashであるにもかかわらず、
ashの名前ではインストールされておらず、
shを名乗ったままシンボリックリンクすら存在しない。

これはおかしい。
211 :名無しさん@お腹いっぱい。2011/07/25(月) 15:34:35.74
>>210
send-prしといて。
213 :名無しさん@お腹いっぱい。2011/07/25(月) 15:56:42.40
>>210
/bin/shのような基本コマンドはカーネルから直接exec()で呼び出されたりもするから
symlinkには出来ないんだよ。システムコールのexec()はsymlinkを追跡しない。
ライブラリのexec()では、内部でreadlink()呼んでsymlinkを追跡するから
気づかないんだけどね。
216 :名無しさん@お腹いっぱい。2011/07/25(月) 19:24:14.52
>>213
じゃあ、ハードリンクでいいじゃない。
218 :名無しさん@お腹いっぱい。2011/07/26(火) 12:22:22.72
内部表現持たないと、扱える正規表現の仕様はかなり小さくなる。
219 :名無しさん@お腹いっぱい。2011/07/30(土) 00:54:06.04
bashでファイルの1行目の10バイト目にある文字だけ置換させたいのですが
どのように書けばいいか教えていただけますでしょうか。
sed、awkコマンドでいろいろやってみたのですが、知識不足で
全行の10バイト目が置換されたりしてなかなかうまくいきません。
回答お願いします。
223 :名無しさん@お腹いっぱい。2011/07/30(土) 09:29:04.52
>>219
せっかくbashならbashの機能使おうや。

(IFS= read -r; echo "${REPLY:0:9}X${REPLY:11}"; cat) < in_file
225 :名無しさん@お腹いっぱい。2011/07/30(土) 11:41:44.30
>>224
特殊機能?

kshでもzshでも使える(>>223 がそのまま動く)汎用機能だが?
294 :名無しさん@お腹いっぱい。2011/08/04(木) 21:08:43.16
>>219の質問に似ているのですが
先頭文字がABCDEで始まるレコードの10バイト目にある文字だけを置換させたいのですが
どのように書けばいいのでしょうか。
297 :名無しさん@お腹いっぱい。2011/08/04(木) 21:27:15.40
>>294
せっかくbashならbashの機能使おうや。

while IFS= read -r; do
case $REPLY in ABCDE*) echo "${REPLY:0:9}X${REPLY:11}";;
*) echo "$REPLY";; esac; done
299 :名無しさん@お腹いっぱい。2011/08/04(木) 21:35:26.56
>>298
特殊機能?

kshでもzshでも使える(>>297 がそのまま動く)汎用機能だが?
220 :名無しさん@お腹いっぱい。2011/07/30(土) 01:42:36.22
sedはパス。awkならこんな感じ。でも多分edの方が速い。
awk 'NR==1{$0=substr($0,1,9)"x"substr($0,11)};1' file

ed -s file <<\EOF
1s/\(.\{9\}\)./\1x/
wq
EOF

もっといい書き方はあるかも。まあこの方法は、10バイト目じゃなくて10文字目なのがもしかしてマズイかも。
221 :名無しさん@お腹いっぱい。2011/07/30(土) 01:50:27.92
ついでだからsedでも書いた。GNU sedなら3つの中で一番遅い方法かな。
sed -n '1s/\(.\{9\}\)./\1x/;p' file
296 :名無しさん@お腹いっぱい。2011/08/04(木) 21:18:38.31
>>294
>>221 の sedの 1s の部分を /^ABCDE/s に置き換えるだけ。
222 :名無しさん@お腹いっぱい。2011/07/30(土) 09:07:27.37
うとうとしながら書くもんじゃねーな。↑は、いらん部分があった。
sed '1s/\(.\{9\}\)./\1x/' file
224 :名無しさん@お腹いっぱい。2011/07/30(土) 11:06:18.91
bashのくせに#!/bin/shとか書いてあるんだからそんな特殊機能なんか使うなよ
227 :名無しさん@お腹いっぱい。2011/07/30(土) 16:28:16.50
シェルスクリプトでのコメントなんてライセンスの主張くらいにしか使わんだろw
228 :名無しさん@お腹いっぱい。2011/07/30(土) 18:45:38.24
おまえは1000行野郎を書いたことがないな
230 :名無しさん@お腹いっぱい。2011/07/31(日) 10:01:27.19
>>228
何それ?
229 :名無しさん@お腹いっぱい。2011/07/31(日) 02:00:07.31
改版履歴とか書いたりして
231 :名無しさん@お腹いっぱい。2011/07/31(日) 11:13:57.94
>>229
せめてRCS使おうぜ
232 :名無しさん@お腹いっぱい。2011/08/02(火) 21:23:22.11
bashで前ゼロ削除をやろうとしているのですが、
初心者のためうまくいきません。すみませんがご教授ください。
00099999

99999
251 :名無しさん@お腹いっぱい。2011/08/03(水) 09:58:20.89
おまえら>>232の細かい仕様が分からないままでよくそんなに遊べるな。
実は、sed 's/000//' ですむ問題かもしれないぞ
258 :名無しさん@お腹いっぱい。2011/08/03(水) 11:49:01.23
おまえらががっつくから>>232が怖がって出てこないじゃねーか
271 :名無しさん@お腹いっぱい。2011/08/03(水) 18:22:33.47
>>232はどこに行ったんだ。
276 :名無しさん@お腹いっぱい。2011/08/03(水) 19:07:03.53
実は別解出し続けた回答者のひとりが >>232 と同一人物。
>>232 は初心者を装ったネタ振り。
233 :名無しさん@お腹いっぱい。2011/08/02(火) 21:31:16.74
expr 00099999 + 0
234 :名無しさん@お腹いっぱい。2011/08/02(火) 21:37:09.94
>>233
こういう風に答えられるように私はなりたい。
echo 00099999 | awk 'sub(/^0+/,"")'
239 :名無しさん@お腹いっぱい。2011/08/02(火) 22:25:25.84
>>233全力スルーでワロタw
248 :名無しさん@お腹いっぱい。2011/08/03(水) 09:34:09.41
直感的なわかりやすさで>>233だな。
既存の文法に無理矢理おさめただけの#って何だよって感じだ。
254 :名無しさん@お腹いっぱい。2011/08/03(水) 11:00:28.45
>>249
expr で >>233 がエラーになる環境って何?

次善策はbcに食わせることかな

echo -00123 | bc
261 :名無しさん@お腹いっぱい。2011/08/03(水) 12:18:58.25
>>259
$ printf '%g' 01234500
1.2345e+06

だめじゃん。

現在の最良回答: >>233 >>235 >>254
263 :名無しさん@お腹いっぱい。2011/08/03(水) 12:35:11.55
小数アリなら >>254 のみ正解か
266 :名無しさん@お腹いっぱい。2011/08/03(水) 12:58:05.76
>>261
まてよ、、指数表記もアリだとしたら…

a=001.2345e+06
echo $a | bc
(standard_in) 1: syntax error
267 :名無しさん@お腹いっぱい。2011/08/03(水) 13:41:25.51
>>233
その発想がすげぇ。
274 :名無しさん@お腹いっぱい。2011/08/03(水) 18:41:36.30
>>233見て、それでも別解出し続けたバカ共の事なんか気にしなくていいだろ。
277 :名無しさん@お腹いっぱい。2011/08/03(水) 19:22:17.13
というか、>>232=>>233だろう。ドヤ顔で>>233を書き込んで盛大に釣り上げた訳だ。やり手だね。
289 :名無しさん@お腹いっぱい。2011/08/04(木) 16:42:26.40
>>267
awkの定石
290 :名無しさん@お腹いっぱい。2011/08/04(木) 17:19:33.47
>>289
awkやってるといつも思うんだが単項+演算子じゃダメなん?
235 :名無しさん@お腹いっぱい。2011/08/02(火) 21:38:17.44
a=00099999
echo $(( 10#$a ))
238 :名無しさん@お腹いっぱい。2011/08/02(火) 22:12:30.31
>>236 は、a=102 とかでも駄目。
ベストアンサー >>235
247 :名無しさん@お腹いっぱい。2011/08/03(水) 08:29:25.47
>>243 >>245
a=-003 とかのときダメ

>>233 と >>235 は
-003 でもOK
249 :名無しさん@お腹いっぱい。2011/08/03(水) 09:34:17.69
符号付きも考えるのかよ…

echo $a | sed 's/^\([+-]\{0,1\}\)00*\(..*\)$/\1\2/'

そういや小数点はどうする?

a=001.3

>>233>>235だとエラーになるぜ
250 :名無しさん@お腹いっぱい。2011/08/03(水) 09:45:31.48
>>249
\?「俺忘れられてね?」
253 :名無しさん@お腹いっぱい。2011/08/03(水) 10:02:05.30
>>250
スマン、、

echo $a | sed 's/^\([+-]\?\)00*\(..*\)$/\1\2/'
265 :名無しさん@お腹いっぱい。2011/08/03(水) 12:48:54.11
>>253がもうちょっとまともに動けば文字列処理型で最善だったかもな。
269 :名無しさん@お腹いっぱい。2011/08/03(水) 17:52:20.58
指数は展開しなくてもいいんじゃ… >>253を使えば"-1.2345e+06"になるし
236 :名無しさん@お腹いっぱい。2011/08/02(火) 21:50:26.85
echo ${a##*0}
237 :名無しさん@お腹いっぱい。2011/08/02(火) 21:55:45.95
>>234,>>236
a=0 だとダメ
243 :名無しさん@お腹いっぱい。2011/08/02(火) 23:24:30.00
echo $a | sed 's/^00*\(..*\)$/\1/'
245 :名無しさん@お腹いっぱい。2011/08/02(火) 23:48:40.41
expr $a : "0*\(..*\)"
257 :名無しさん@お腹いっぱい。2011/08/03(水) 11:47:40.69
printf '%d' 00099999
じゃだめか?
259 :名無しさん@お腹いっぱい。2011/08/03(水) 11:51:38.84
>>257
printf '%d' 00011111とかやると2進数だとして処理されちゃうので
printf '%g' の方がいい

268 :名無しさん@お腹いっぱい。2011/08/03(水) 17:30:18.84
たぶん >> 233 で FA だと思うが…

>> 266
a="-001.2345e+06"
echo $a | sed 's/\([0-9.]*\)[Ee]\([+-]\?[0-9]*\)/\1*10^(0\2)/' | bc
-1234500.0000
270 :名無しさん@お腹いっぱい。2011/08/03(水) 18:09:09.98
よし、俺が仕様を決めてやるよ

入力:10進数、正負あり、小数可、指数表記可
出力:10進数、入力と数値的に等しい最短の文字列、指数表記可
275 :名無しさん@お腹いっぱい。2011/08/03(水) 18:52:59.80
バカはともかく、お題を楽しんでるだけなんだから、質問者放置でよし
質問やり逃げなんていつものこと
279 :名無しさん@お腹いっぱい。2011/08/03(水) 22:32:05.53
ファイルに改行コードがあるかどうか判定し、なければ10バイト目に
改行コードを入れるbashを教えてください。。。。
280 :名無しさん@お腹いっぱい。2011/08/03(水) 22:43:40.70
>>279
/bin/bash
282 :名無しさん@お腹いっぱい。2011/08/04(木) 00:27:02.64
>>279
エスパー解釈すると、ファイルに一切改行がない場合のみ、
1行10文字で改行を入れる、ということでいいかな。


case `wc -l < file` in
0) fold -10 file;;
*) cat file;;
esac
281 :名無しさん@お腹いっぱい。2011/08/04(木) 00:21:46.47
↓のようなテキスト(sample.txt)があり
aaa 1
xxx 2
bbb 3
aaa 4
aaa 5
xxx 6
bbb 7
xxx 8
aaa 9
「xxx」以降、最初に出現した「aaa」の後に続く数字を出力しようと思っています。
上記テキストの場合、期待する結果は4と9です。
そこで以下のようなスクリプトを作りました。
#! /bin/sh
cat sample.txt |
awk '/xxx/{
while ( getline > 0 ){
if ($0 ~ /aaa/) {
print $2;
break;
}
}
}'
期待した動作はするのですが、「xxx」を見つけたら→その後一行ずつ探す、という実装で
ちょっと力技すぎるかな?と思ってます。
xxxを検索条件としている所と、if文中でaaaと比較する所とで、方法がマチマチなので
これってどうなのだろうか、と。
かといって全てwhileループ内に入れて、まずxxxだったら…というのもイマイチかと…

よりうまい書き方とかありましたら、教えてください。
284 :名無しさん@お腹いっぱい。2011/08/04(木) 00:41:54.94
>>281
いくつか思いついたけど、できるだけそれを尊重してフラグを使う方法にしてみた。
cat sample.txt | awk 'z&&/aaa/{z=0;print$2};/xxx/{z=1}'

sedでも書けそう。perlならもっと短く書けるかな?
283 :名無しさん@お腹いっぱい。2011/08/04(木) 00:31:55.31
迷わずperl
perl -n -e 'if ((/^xxx/ .. /^aaa/) && /^aaa\s+(\d+)/) { print "$1\n"}' < sample.txt
285 :名無しさん@お腹いっぱい。2011/08/04(木) 00:48:02.52
>>283
perlで書くとこうなるのか。ちょっと意外。
それ見てawkも範囲指定できること思い出した。
awk '/xxx/,/aaa/{if(/aaa/)print$2}' sample.txt
これ以上簡単に書ける方法は思いつかんかった。
288 :名無しさん@お腹いっぱい。2011/08/04(木) 12:01:18.20
>>283-287
皆さん情報ありがとうございました

いろいろ新しい発見をしました
いただいた情報をもとに、修正の方針など検討します
286 :名無しさん@お腹いっぱい。2011/08/04(木) 00:53:18.58
再々修正。同じ正規表現を使うのは非効率なので結果を再利用。
awk '/xxx/,a=/aaa/{if(a)print$2}' sample.txt
287 :名無しさん@お腹いっぱい。2011/08/04(木) 01:04:20.50
じゃ、sedで

sed -n '/^xxx/,/^aaa/{s/^aaa \([0-9]\+\)/\1/p}' < sample.txt

範囲指定のregexpを{}内から参照ってできないんだっけか
291 :名無しさん@お腹いっぱい。2011/08/04(木) 17:35:14.32
+ 0 (as number)は . "" (as string)と対称構造を持つ定石。
293 :名無しさん@お腹いっぱい。2011/08/04(木) 18:10:14.75
>>291
ありがとう。そういうことか。演算子の優先順位が違うから専用の演算子でも欲しいところだ。
295 :名無しさん@お腹いっぱい。2011/08/04(木) 21:18:07.50
直ぐ下のレスのawkスクリプトのNR==1を/^ABCDE/にすればいいと思うの。
298 :名無しさん@お腹いっぱい。2011/08/04(木) 21:31:01.38
bashのくせに#!/bin/shとか書いてあるんだからそんな特殊機能なんか使うなよ
300 :名無しさん@お腹いっぱい。2011/08/05(金) 10:10:22.29
read で変数を指定しなかったときに $REPLY に入れるとか、
${var:m:n} で変数から文字を切り出すってのは
ksh 系の機能で sh にはない機能だよね。
少なくとも、/bin/sh が dash や ash である OS では動かない。
301 :名無しさん@お腹いっぱい。2011/08/05(金) 10:52:47.50
>>300
> read で変数を指定しなかったときに $REPLY に入れるとか、

なんでこんな馬鹿な仕様を新設したんだろうな。
302 :名無しさん@お腹いっぱい。2011/08/05(金) 21:37:43.68
リハ用のシェルのソースで、
ふざけ心で変数無指定時にはREPLYに入れるようにしておいたら、
誤って本番のソースとして流れてしまったんです。
304 :名無しさん@お腹いっぱい。2011/08/05(金) 22:34:37.22
誤ってコミットしてしまい、23秒間Ctrl-Cを押し続けたんですけど取り消せませんでした
306 :名無しさん@お腹いっぱい。2011/08/11(木) 10:25:22.54
rsync で相互同期(src と dst で共に更新がありえて、新しい方を採用)する場合って、
rsync -u src dst
rsync -u dst src
すればできますが、時間がかかります。
一発でやる方法ありますか?
また、rsync じゃなくてコレならそれを一発でできるよみたいのありますか?
307 :名無しさん@お腹いっぱい。2011/08/11(木) 11:05:23.86
312 :名無しさん@お腹いっぱい。2011/08/12(金) 04:05:08.93
>>307 ビンゴです。アリガトン!
308 :名無しさん@お腹いっぱい。2011/08/11(木) 21:55:08.20
shまたは、bashで、
コマンドをタイムアウトさせる関数timeoutを作りたい。
timeout [タイムアウト秒数] [コマンド]

で、
指定[タイムアウト秒数]以内に[コマンド]が終了した場合は、
その[コマンド]の終了コードを、
[タイムアウト秒数]に引っかかった場合は、timeout関数の終了コードを返す。

そんな関数って書けますか?
309 :名無しさん@お腹いっぱい。2011/08/11(木) 21:56:35.05
追記、
もちろん[タイムアウト秒数]に引っかかった場合は、
[コマンド]を強制終了させます。
311 :名無しさん@お腹いっぱい。2011/08/11(木) 23:46:06.76
どうやって?
314 :名無しさん@お腹いっぱい。2011/08/12(金) 10:56:57.06
>>311
こんな感じでやりましタ。行数の問題で見にくいですが。

timeout() {
TIMEOUT=$1
shift 1
"$@" &
PID=$!
PASSED_SEC=0
while [ ${PASSED_SEC} -lt ${TIMEOUT} -a `ps -p ${PID} | grep -cv PID` -ne 0 ]
do
PASSED_SEC=`expr ${PASSED_SEC} + 1`
sleep 1
done
if [ `ps -p ${PID} | grep -cv PID` -ne 0 ]; then
kill -KILL ${PID}
wait ${PID}
echo "$@: killed, for timeout(${TIMEOUT}sec) exceeded." >&2
return 1
fi
wait ${PID}
return $?
}
315 :名無しさん@お腹いっぱい。2011/08/12(金) 21:18:57.02
>>314
別にcoreutilsに入っているtimeoutコマンドをエミュレートしたかった訳じゃないのね。
313 :名無しさん@お腹いっぱい。2011/08/12(金) 09:08:38.64
unison昔試したときイマイチ挙動が安定しなかったんだよな
更新かけたファイルがたまに消えたり。
今は良くなったかな?
316 :名無しさん@お腹いっぱい。2011/08/12(金) 22:08:40.27
denコマンド作ったよ

$ den
-- 東京電力 -------------------------
2011/8/12 21:55 UPDATE
PEAK供給力: 5480 万kW
21:55: 3771 万kW (68%)
-- 東北電力 -------------------------
2011/8/12 22:02 UPDATE
PEAK供給力: 1228 万kW
22:00: 884 万kW (71%)
-- 関西電力 -------------------------
2011/8/12 21:55 UPDATE
PEAK供給力: 2850 万kW
21:45: 2081 万kW (73%)
321 :名無しさん@お腹いっぱい。2011/08/15(月) 12:57:15.16
dmesgの先頭の
[ 0000.000] を削除したいんですが
どうすればできますか
324 :名無しさん@お腹いっぱい。2011/08/15(月) 13:58:58.03
>>321

dmesg | sed 's/[^ ]* //'
326 :名無しさん@お腹いっぱい。2011/08/15(月) 14:06:11.38
>>325
条件後出しじゃなくて、
>>322 は最近のLinuxのdmesgを良く知らずに回答してると思われる。

>>324 が正解のひとつ
327 :名無しさん@お腹いっぱい。2011/08/15(月) 14:29:49.97
>>324 は不正解だろ。
こっち正解

dmesg | sed 's/[^]]*[]] //'
322 :名無しさん@お腹いっぱい。2011/08/15(月) 13:08:25.41
sed 's/^\[ 0000\.000\]//'
323 :3212011/08/15(月) 13:51:10.11
>322
ありがとうございます。
ただ
全部の行の[ 4.01234] などをずべて消したいです
325 :名無しさん@お腹いっぱい。2011/08/15(月) 13:59:39.32
条件後出しかよ。
328 :名無しさん@お腹いっぱい。2011/08/15(月) 14:34:10.87
dmesg | sed 's/.*\] //'
329 :名無しさん@お腹いっぱい。2011/08/15(月) 14:40:28.88
>>328
不正解。
それだと dmesg中の [8086:0040] type 0 class みたいな行の [8086:0040] の部分まで
消えてしまう。
332 :名無しさん@お腹いっぱい。2011/08/16(火) 19:06:44.80
bashでファイルの先頭が’A’で始まるレコードの10バイト目から12バイト目までが
’空白’(スペースが3個)であれば、その空白を’XXX'に変換したいのですが
うまくいきません、良い書き方教えてくださ
333 :名無しさん@お腹いっぱい。2011/08/16(火) 19:07:28.10
bashでファイルの先頭が’A’で始まるレコードの10バイト目から12バイト目までが
’空白’(スペースが3個)であれば、その空白を’XXX'に変換したいのですが
うまくいきません、良い書き方教えてくださ
334 :名無しさん@お腹いっぱい。2011/08/16(火) 20:50:11.25
>>333
sed -e '1s/\(A.\{8\}\) /\1XXX/'
335 :名無しさん@お腹いっぱい。2011/08/16(火) 20:58:42.93
しまった。2chに書くと空白3つが一つに変換されてしまうのね。
sed -re '1s/(A.{8}) {3}/\1XXX/'
338 :名無しさん@お腹いっぱい。2011/08/16(火) 22:54:31.69
>>337
ああ、確かに>>334,>>335は間違いだった。スマン。
正しくは
sed -re '1s/^(A.{8}) {3}/\1XXX/'
だな。

これは
「一行目の先頭の文字がAであり、その後に任意の文字が8文字続き、そのあとに空白が3文字続いたなら
その部分を()でマッチした部分+XXXに置き換える」
という意味。
もっと詳しいことが知りたかったらsedとか正規表現でググると良いぞ。
336 :名無しさん@お腹いっぱい。2011/08/16(火) 21:37:58.18
&nbsp;ではなく{3}使ってくるとかワラタw
337 :名無しさん@お腹いっぱい。2011/08/16(火) 22:35:00.01
>>335
初心者のためあまりよく分からないのですが、
10バイト目から12バイト目が’空白’の条件は
どうやっているのでしょうか。。。
>>336
あと を使う書き方は{3}を に変えるだけで
よいのでしょうか。
340 :名無しさん@お腹いっぱい。2011/08/19(金) 14:52:03.70
対した事の無い処理をわざわざ複雑に書くのはただの馬鹿。
perl一つで解決する物をsed使ったりして頑張っちゃうとか
341 :名無しさん@お腹いっぱい。2011/08/19(金) 15:22:53.37
sed一つで済むのにわざわざperlを使っちゃうのも如何なものだと思うけど。
342 :名無しさん@お腹いっぱい。2011/08/19(金) 15:43:28.04
わざわざっつーか、汎用テキスト処理スクリプトであるPerlを使っちゃうと
スクリプトの意味が解りにくくなるんよね。
sedだったら、まず最も多い用途は置換だから、置換かな?と思って読むことが出来る。
もちろん、複雑なテキスト処理に使うのは大賛成だけどね。
343 :名無しさん@お腹いっぱい。2011/08/19(金) 16:01:18.18
大半のテキスト処理はsedとawkがあればできちゃうからなあ。
Perlじゃないとできないことは滅多にないし
Perl書くぐらいならRubyかPythonで書いちゃう。
344 :名無しさん@お腹いっぱい。2011/08/19(金) 16:07:50.83
まあ、重たい処理ならPerlオンリーでも良いんじゃね?
シェルスクリプトだとどうしても処理長くなっちゃうし。
ただまあ、ここはシェルスクリプトのスレなんだよな。
345 :名無しさん@お腹いっぱい。2011/08/19(金) 18:50:17.85
まあおいらが言いたかったのは列抜き出すだけで単純にawkで済むものをsed使って正規表現の置換で無理やり見たいのをこのスレでよく見るからさ
本人はスキルを自慢しているつもりなんだろうけど、見辛いだけなんだよね
可視性も考慮しろと言いたい
349 :名無しさん@お腹いっぱい。2011/08/19(金) 19:51:31.19
>>345
全く逆

単純にsedで済むものは必ずsedで書くこと。
sedで書けない処理の場合のみawkで書く。
sedで書けるのにわざわざawk使うのはバカ。

sedもawkも使わずにシェルだけで書けるものはシェル(内部コマンド)で書く。


(おまけ) perlで書くのは無条件で馬鹿。
346 :名無しさん@お腹いっぱい。2011/08/19(金) 18:54:44.18
まあ、いいんじゃないの?
ここは初学者用の教科書じゃないんだから。
自治厨より役に立つ。
347 :名無しさん@お腹いっぱい。2011/08/19(金) 18:59:05.65
と言うか個人的な好みも有るかもしれないが、sedは見た目がきたない
正規表現で置換をやるなら何故perlを使わないのか理解に苦しむ
まあスレチですが…
348 :名無しさん@お腹いっぱい。2011/08/19(金) 19:04:48.19
そもそも正規表現自体が汚いんだからperl使おうがsed使おうが一緒だろ
まあスレチですが…
350 :名無しさん@お腹いっぱい。2011/08/19(金) 21:44:24.56
perlって、awkの機能もsedの機能もgrepの機能も持ってるじゃん
awk、sed、grep使ってる程度のシェルスクリプトって、perlで書こうと思えば書けちゃうじゃん
だから全部perlで書くなら、別にいいと思うんだよ

でも、シェルスクリプト中で、awkやsed、grepでできる処理をperlで書くっていうのは、
それはなんかイケてないって気がするんだよな

逆に、perlでなきゃ無理な処理をシェルスクリプトに混ぜ込むってのも、perlを必要とするなら
全部perlで書いちゃえyo、とも思うんだよな

なんというか、シェルもperlも、スクリプト動かせる土台じゃん、と
まぁawkも結構いろいろできるけど、それはそれとして、さ
353 :名無しさん@お腹いっぱい。2011/08/19(金) 22:11:59.95
sedで充分なのはsedで、不十分なのはperlで、pythonはワンライナー書けないから却下。
awkの出番はほぼ無い。唯一「n番目のフィールドを取り出す」これだけがawkを使う場面。
354 :名無しさん@お腹いっぱい。2011/08/19(金) 23:44:48.77
>>353
そんだけならcutでいいでしょ。

だから、不十分なのはperlでって、本当に不十分なんすかね?という話になる。
355 :名無しさん@お腹いっぱい。2011/08/19(金) 23:53:21.61
>>354
cutは文字列をセパレータに出来ないじゃん。使い分けるの面倒だからその用途にはawkで良い。
356 :名無しさん@お腹いっぱい。2011/08/20(土) 00:18:53.90
>>354
cutでawkと全く同じようにフィールド切り出せるの?
357 :名無しさん@お腹いっぱい。2011/08/20(土) 17:20:50.24
linux環境上で120MBぐらいのファイルの文字コード変換を
iconvコマンドで別ファイル書き出すbashを作成していたのですが、
エラーが出てしまいました。エラー内容がうろ覚えなのですが、
(たしか容量的な問題のエラー)
容量の問題かと思い調べたのですが、2GBまでは大丈夫そうなのですが
何か他に問題てありますか。。。
358 :名無しさん@お腹いっぱい。2011/08/20(土) 19:09:59.84
bashというのは名前からしてシェルですか?
でも、すでにbashという名のシェルは存在するので、別の名前にした方が良いですよ。
359 :名無しさん@お腹いっぱい。2011/08/20(土) 19:41:06.50
>>357
iconv に -c オプションを付けろ。
-c がないとiconvで変換できない文字コードに出会った時に異常終了する。


>>358
エスパー失格の上に返しがつまんね
360 :名無しさん@お腹いっぱい。2011/08/20(土) 19:54:25.02
>>359
エスパーさんは隔離スレから出てこないでください。隔離スレに回答待ってる質問者がいますよ。
361 :3592011/08/20(土) 20:48:13.07
>>360
俺はそっちのスレの住人じゃないよ。
他板でも、エスパー回答はごく当たり前の風潮。
364 :名無しさん@お腹いっぱい。2011/08/21(日) 08:38:40.08
現在のディレクトリ以下のディレクトリ、ファイルから再帰的に
目的の文字列を検索て、フルパスを一覧表示したいです。
どうすればよいですか
365 :名無しさん@お腹いっぱい。2011/08/21(日) 08:45:48.09
それはシェルスクリプトでやるべきではありません。とても遅くなるからです。
366 :名無しさん@お腹いっぱい。2011/08/21(日) 09:50:41.06
find . | xargs grep "AAA"
では


369 :名無しさん@お腹いっぱい。2011/08/21(日) 10:41:00.74
>>366
それ、今時のスペース入りファイル名で誤動作するから禁止。
「xargsは使うな」っていうテンプレ、前スレまであったのになくなったな。
381 :名無しさん@お腹いっぱい。2011/08/21(日) 13:48:05.92
>>369
昔は誤動作しなかったの?
384 :名無しさん@お腹いっぱい。2011/08/21(日) 14:22:00.06
>>381
昔はファイル名にスペースなんか入れないことが暗黙の了解だった。
CUIのみの操作だから、スペース入りファイル名は作りにくいし作らない。
だから、-0なしのxargsが普通に使われていた。
370 :名無しさん@お腹いっぱい。2011/08/21(日) 10:44:31.30
$ find . -print0 | xargs -0 AAA
でいいっしょ。
371 :名無しさん@お腹いっぱい。2011/08/21(日) 10:50:24.40
>>370
それはGNU限定になるから没。(しかもgrep忘れてるしw)

find . -exec grep AAA {} +
が正解。
(最後 + がポイント)
372 :名無しさん@お腹いっぱい。2011/08/21(日) 10:53:09.46
>>371
最後の+は古いバージョンのfindじゃ使えないんじゃないの?
373 :名無しさん@お腹いっぱい。2011/08/21(日) 10:57:18.19
>>371
の方法に別に異論はないけどFreeBSDのfind/xargsにも -print0/-0はあるみたい。
393 :名無しさん@お腹いっぱい。2011/08/22(月) 06:52:56.26
>>392
grep に渡されるファイル名が1つだけの場合は起こりえない。
>>371 では、あえて -type f を付けていない。
だから、カレントディレクトリの . が必ず渡されるため、
それと通常ファイルを含めて2個以上の引数がgrepに渡る。
401 :名無しさん@お腹いっぱい。2011/08/24(水) 14:28:13.26
>>393
最初に実行される grep についてはそうなんだが、ファイルがたくさんあって、
渡される引数が ARG_MAX を超えたときに別のプロセスとして実行される
grep でも起こり得ないんだろうか。まぁ、めったにはおこらないと思うが…

そもそもこれを想定しないで良いなら grep AAA `find ./` でいいわけだし。
402 :名無しさん@お腹いっぱい。2011/08/24(水) 14:35:51.85
>>401
>grep AAA `find ./` でいいわけだし。

↑ それ、スペース入りファイル名で誤動作。で、話がループ。
404 :名無しさん@お腹いっぱい。2011/08/24(水) 17:17:40.10
>>402
grep AAA "`find ./`" でいいわけだし。
374 :名無しさん@お腹いっぱい。2011/08/21(日) 11:59:28.74
+が使えるなら-print0も使えるってオチとか無いの?w
377 :名無しさん@お腹いっぱい。2011/08/21(日) 12:20:24.86
>>374
Solarisでは +は使えるが -print0は使えない
375 :名無しさん@お腹いっぱい。2011/08/21(日) 12:03:11.21
むしろgrep -r -nで|sedで削って| uniqとかでまとめちゃうとかw
376 :名無しさん@お腹いっぱい。2011/08/21(日) 12:06:04.28
>>375
何をしたいのかよく分からないけどgrep -r -lとは違うの?
379 :名無しさん@お腹いっぱい。2011/08/21(日) 12:45:56.74
xargsを使っちゃいけないってことはhogeにファイル名の一覧があるとして
$ tr '\n' '\0' < hoge | xargs -0 grep AAA
みたいなことをしたい場合はどうすればいいの?
380 :名無しさん@お腹いっぱい。2011/08/21(日) 13:47:08.25
>>379

IFS='
'
grep AAA `cat hoge`
385 :名無しさん@お腹いっぱい。2011/08/21(日) 14:30:57.34
>>380
それ、スペースはOKだけど、* ? [ab] とかのワイルドカードが展開される。

set -f 追加しろ。
390 :名無しさん@お腹いっぱい。2011/08/21(日) 19:16:17.14
>>387 のページより、

IFS="$(printf '?n?t')"
# CORRECT if filenames can't include tab/newline *and* if IFS omits space:
COMMAND $(find .)

↑ 駄目だよ。
>>385 が言うように set -f しないと、
findしたファイル名に素の * とかが含まれていると、それが再度展開される。
382 :名無しさん@お腹いっぱい。2011/08/21(日) 13:53:56.90
-0もできないような古いOSなんか使ってるんじゃねぇってことじゃね?
383 :名無しさん@お腹いっぱい。2011/08/21(日) 14:16:06.89
find ./ -type f -exec grep AAA {} /dev/null \;
てのがよくある方法だと思ったが
392 :名無しさん@お腹いっぱい。2011/08/21(日) 23:25:52.93
>>371
最後 + だと grep に渡されるファイル名が1つだけの場合が起こり得る。
>>383 はそれを回避できるが、まぁ効率は悪いな。
「フルパスを一覧表示」だから、素直に -l オプションつければいいんじゃないか?

find ${PWD}/ -type f -exec grep -l 'AAA' /dev/null {} +

/dev/null は "-e" のような名前のファイルがあっても動くように入れてみた。
395 :名無しさん@お腹いっぱい。2011/08/22(月) 12:03:59.75
>>366
$ find . | xargs grep "AAA"
grep: ./oppai: そのようなファイルやディレクトリはありません
grep: oppai: そのようなファイルやディレクトリはありません
grep: ./oppai: そのようなファイルやディレクトリはありません
grep: oppai/oppai: そのようなファイルやディレクトリはありません
grep: text.txt: そのようなファイルやディレクトリはありません

>>370
$ find . -print0 | xargs -0 grep AAA
./oppai oppai/oppai text.txt:AAA

>>371
$ find . -exec grep AAA {} +
./oppai oppai/oppai text.txt:AAA

>>383
$ find ./ -type f -exec grep AAA {} /dev/null \;
./oppai oppai/oppai text.txt:AAA

>>392
$ find ${PWD}/ -type f -exec grep -l 'AAA' /dev/null {} +
/tmp/oppai oppai/oppai text.txt
386 :名無しさん@お腹いっぱい。2011/08/21(日) 17:29:00.39
なぜファイル名にスペース禁止にしなかったのかほんとに意味が分からない
387 :名無しさん@お腹いっぱい。2011/08/21(日) 17:53:00.44
「Filenames in Shell」
http://www.dwheeler.com/essays/filenames-in-shell.html
これ参考になりそうだけど全部英語なのでキツい。誰か翻訳しませんか。
388 :名無しさん@お腹いっぱい。2011/08/21(日) 18:59:58.18
>>387
ありがとう。参考になったよ。この程度の英語ならそのまま読める。
"mojibake"だけ日本語だった。これって英語圏でも通じる言葉になったのかw
389 :名無しさん@お腹いっぱい。2011/08/21(日) 19:06:56.58
シェルスクリプトを勉強する前に、Perlを勉強することにしましたw
396 :名無しさん@お腹いっぱい。2011/08/22(月) 12:06:50.88
AAAじゃなくxだったらどうなる?
397 :名無しさん@お腹いっぱい。2011/08/22(月) 12:13:17.20
>>396
$ find . | xargs grep "x"
grep: ./oppai: そのようなファイルやディレクトリはありません
grep: oppai: そのようなファイルやディレクトリはありません
grep: ./oppai: そのようなファイルやディレクトリはありません
grep: oppai/oppai: そのようなファイルやディレクトリはありません
grep: text.txt: そのようなファイルやディレクトリはありません
$ find . -print0 | xargs -0 grep x
$ find . -exec grep x {} +
$ find ./ -type f -exec grep x {} /dev/null \;
$ find ${PWD}/ -type f -exec grep -l 'x' /dev/null {} +
398 :名無しさん@お腹いっぱい。2011/08/22(月) 12:22:54.38
Binary file なんちゃらって出るのはBSD限定?
NFSだと別の表示になるかもしれんが。
399 :名無しさん@お腹いっぱい。2011/08/22(月) 12:56:08.85
ufsだとディレクトリが読めちゃうよね。
NFSだと読めないし、ext[234]でもディレクトリは読めない。
他のファイルシステムはどうだろう?

あと、検索対象のファイルがバイナリファイルだった場合、
古いgrepだとBinary ...のエラーで門前払いされて
中身を検索してくれないことがある。GNU grepだとバイナリでもOK。
400 :名無しさん@お腹いっぱい。2011/08/23(火) 12:41:14.11
zfsでも$ cat .
とかできちゃうな。
この辺の挙動の違いってファイルシステムじゃなくて
FreeBSDとLinuxのシステムコールの実装の違いだと思ってたんだけど違うのかな。
405 :名無しさん@お腹いっぱい。2011/08/24(水) 19:12:50.20
grep pattern filename* /dev/null
は定石かと。
407 :名無しさん@お腹いっぱい。2011/08/24(水) 19:28:14.75
>>405
それ、過去のバッドノウハウな。

今は -H オプションがあるから grep -H hoge file*
413 :名無しさん@お腹いっぱい。2011/08/24(水) 22:58:28.01
>>412
発端は >>405

どう見てもワイルドカードです。
408 :名無しさん@お腹いっぱい。2011/08/24(水) 19:49:37.05
-Hは0個に対応できないでしょ。file+にしか。
409 :名無しさん@お腹いっぱい。2011/08/24(水) 20:04:50.08
>>408
0個の場合は findから呼び出されないから無問題。
411 :名無しさん@お腹いっぱい。2011/08/24(水) 20:17:16.93
>>408
コマンドライン直接の話だとしても、

ファイルが0個の場合は file* って文字列自体が grepの引数になってエラーになるだけ
だから、stdinを読んでしまうことはない。
file* の文字列自体が渡ってしまうことは /dev/nullを付けても解決しない。
410 :名無しさん@お腹いっぱい。2011/08/24(水) 20:06:25.45
そんなこと全く気にしたことが無かったのだが、その/dev/nullは、運悪く渡されるファイルがなかったときに、
標準入力を読みに行ってシェルスクリプトが固まるのを防ぐためのもの…なのか?
412 :名無しさん@お腹いっぱい。2011/08/24(水) 22:51:09.55
file*は正規表現のつもりなんじゃないの? +とか書いてるし。
414 :名無しさん@お腹いっぱい。2011/08/24(水) 23:38:26.66
質問です。

以下のようなスクリプトがあります。
-------------------------
$ cat ./hoge.sh
#!/bin/sh -x
find . -type f | wc -l
-------------------------

このスクリプトを実行すると、通常以下のように出力されます。
-------------------------
$ ./hoge.sh
+ find . -type f
+ wc -l
1
-------------------------

しかし、時々以下のように変な出力がされることがあります。なぜでしょうか?
そして、回避策はありますか?
-------------------------
$ ./hoge.sh
+ find+ wc /home/mao/tmp/110824 -l -type
f
1
-------------------------
417 :名無しさん@お腹いっぱい。2011/08/24(水) 23:57:54.89
>>414
質問とは直接関係ないけど、
それ、改行入りファイル名で誤動作するから使用禁止。
425 :名無しさん@お腹いっぱい。2011/08/25(木) 09:23:19.55
行ごとflushならマルチコアでも>>414の問題置きなくね?
415 :>>4142011/08/24(水) 23:39:55.88
すいません、最後のサンプルだけ訂正させてください
-------------------------
$ ./hoge.sh
+ find+ wc . -l -type
f
1
-------------------------

427 :名無しさん@お腹いっぱい。2011/08/25(木) 09:47:13.83
同様に、単語ごとflushでもシングルコアなら >>415 の現象は起きにくい。
428 :名無しさん@お腹いっぱい。2011/08/25(木) 10:13:07.83
>>427
アホは書きこむな。
416 :>>4142011/08/24(水) 23:41:34.43
私が思うに、パイプの左と右が一緒に実行されるのでは?と疑っています。
418 :名無しさん@お腹いっぱい。2011/08/25(木) 00:09:59.39
>>416
パイプの左と右が同時に実行される、で正解だよ。それで仕様。
嫌な場合はBIOSでCPUを1コア以外止める。
419 :名無しさん@お腹いっぱい。2011/08/25(木) 00:11:07.08
>>418
いやいや、1コアでも無理でしょ
420 :名無しさん@お腹いっぱい。2011/08/25(木) 08:26:15.19
>>419
いいや、1コアなら大丈夫。
ヒント:プリミティブ
429 :名無しさん@お腹いっぱい。2011/08/25(木) 10:18:09.31
で、ありがたいヒントくださった>>420どこいった?
421 :名無しさん@お腹いっぱい。2011/08/25(木) 08:51:25.98
1単語出すごとにflushしてるのに?
423 :名無しさん@お腹いっぱい。2011/08/25(木) 09:15:14.31
>>421
flushは行ごと。(確認済み)
422 :名無しさん@お腹いっぱい。2011/08/25(木) 09:12:50.11
Windows7 UltimateにあるUnix互換モードって普通のunixみたいに使えるものなの?bashとかもあるらしいのだけど
433 :名無しさん@お腹いっぱい。2011/08/25(木) 11:42:56.62
>>422
ターミナルの画面がでかくできない
コピーペーストできない

つかえない
424 :名無しさん@お腹いっぱい。2011/08/25(木) 09:21:01.39
シェルの実装依存だろ
set -x のデバッグメッセージについては、

ksh zsh bash: 行ごとflush
ash: 単語ごとflushw
426 :名無しさん@お腹いっぱい。2011/08/25(木) 09:28:30.56
>>424
jshも単語ごとだね
v7shは明示的にはflushしてなさそうだけど、単語ごとwrite
430 :名無しさん@お腹いっぱい。2011/08/25(木) 10:41:34.33
>>424がFA
432 :名無しさん@お腹いっぱい。2011/08/25(木) 10:57:42.21
>>430
質問者への回答になってない
435 :名無しさん@お腹いっぱい。2011/08/27(土) 05:01:57.93
質問です.
set -x による出力が

+ date -d '2011/4/2 6 day' +%Y

のようになっていて,その次の出力行が

date: 余分な演算子 `day\''
詳しくは `date --help' を実行して下さい.

と出力される箇所があるのですが,-xの出力をそのまま端末エミュレータに
コピペしてみると正しく実行されます.
このエラーの原因が分からなくて困っています.
どなたか助けてください.よろしくお願いします.
436 :名無しさん@お腹いっぱい。2011/08/27(土) 09:37:12.48
>>435
シングルクォートが、通常の文字として解釈されてる。
シングルクォートが余分。
あるいは、もう1回解釈させるために
evalを付けると良い。

再現方法:
$ date -d "'"2011/4/2 6 day"'" +%Y
date: 余分な演算子 `day¥''
詳しくは `date --help' を実行して下さい。
437 :名無しさん@お腹いっぱい。2011/08/27(土) 09:49:38.05
>>435
エスパー回答するぞ。他の変数にdateの引数入れてるんだろ?

$ hoge="-d '2011/4/2 6 day' +%Y"
$ date $hoge
date: 余分な演算子(ry

$ eval date $hoge
2011


>>436 の言うようにevalで解決。
438 :4352011/08/27(土) 16:35:27.84
>>436,437
evalで解決できました.ありがとうございました.

ちなみに,>>437さんの言うように,dateの引数を変数に入れて使ってました.
440 :名無しさん@お腹いっぱい。2011/09/04(日) 08:24:10.51
Ubuntuっつーか、Debian系で使われるのがdash(Debian ash)だな、ashのDebian版
Debian系では対話環境のデフォルトはbash、シェルスクリプトはdashを前提とすることが多い
Ubuntuの/bin/shも確か中身はdashなんだっけ?

ちなみにお約束に追記するとしたら、どの辺にどう追記するよ?
441 :名無しさん@お腹いっぱい。2011/09/04(日) 15:37:58.36
見てきた
sh -> dash てなってた
知らんかったわ@Ubuntu
442 :名無しさん@お腹いっぱい。2011/09/04(日) 15:56:28.15
>>440
>>Linuxユーザは/bin/shの正体がbashなので特に注意。
>>FreeBSDユーザは/bin/shの正体がashなので注意。
の下に一緒にいれときゃいいんじゃないかな?
>>441
if [[ "${foo}" =~ "${foo}" ]]; then 〜fi
みたいな式が使えなくてさ・・・「何で?デフォルトのshはbashにリンクされてるんじゃないの?」
って思って調べてみたら・・・
454 :名無しさん@お腹いっぱい。2011/09/05(月) 04:33:29.14
>>442
> if [[ "${foo}" =~ "${foo}" ]]; then 〜fi
> みたいな式が使えなくてさ・・・「何で?デフォルトのshはbashにリンクされてるんじゃないの?」
状況が分からないけど、 bash 特有の機能を使うときは、シェバングを
/bin/bash などに変えたほうが良いと思う。
443 :名無しさん@お腹いっぱい。2011/09/04(日) 16:02:43.65
950あたりでまた言ってくれ。
453 :名無しさん@お腹いっぱい。2011/09/04(日) 23:04:02.49
>>442
「Debian系Linux(Ubuntuなど)では/bin/shの正体がdash(Debian版ash)だったりするので注意。」
って感じかな、>>443 の言う通り >>950 辺りでまた言ったほうが良いかもね
462 :名無しさん@お腹いっぱい。2011/09/05(月) 14:24:44.74
実際、ほとんどのUbuntu(Debian)ユーザーは >>460 で
/bin/sh -> bash に設定してるよ。
だから、Debian系Linux(Ubuntuなど)では/bin/shの正体がdash」(>>453)
と言うとそれはそれで嘘になる。
463 :名無しさん@お腹いっぱい。2011/09/05(月) 14:41:01.80
>>462
だから>>453では「だったりする」という書き方にしてるんだよ。
470 :名無しさん@お腹いっぱい。2011/09/06(火) 01:21:53.69
>>462
してないしてないw
シェルスクリプト走らすのにいちいちフットプリントのデカいbashなんか使わん
444 :名無しさん@お腹いっぱい。2011/09/04(日) 17:11:34.08
AIX6.1環境に旧サーバーからのアプリケーション移行を行ってるんですが
その際不要なファイルが大量にあり、一括表示する方法はないものかと
あれこれ試してみました。

結果として下記のような記述になったのですが…(色々省略してますが)

$ echo "ls -l $1 "`while read line do; echo "grep -v "$line ;done < $2` > 不要ファイル一覧表示.ksh
$ 不要ファイル一覧表示.ksh
$ rm 不要ファイル一覧表示.ksh

$1は検索対象ディレクトリ、$2は必要ファイル一覧です

不要ファイル一覧表示.kshの生成と削除を行わず、いきなり実行は出来ないんでしょうか?
445 :名無しさん@お腹いっぱい。2011/09/04(日) 17:22:46.04
echo "ls -l $1 "`while read line do; echo "grep -v "$line ;done < $2` | ksh
446 :名無しさん@お腹いっぱい。2011/09/04(日) 18:37:56.77
>>445
なるほど、ありがとうございます!
あと自分の記述が間違えてた…
$ echo "ls -l $1 "`while read line do; echo "|grep -v "$line ;done < $2` > 不要ファイル一覧表示.ksh
パイプ入れ忘れ〜
452 :名無しさん@お腹いっぱい。2011/09/04(日) 20:14:15.92
>>446
セミコロンの位置とかいろいろ間違えすぎだろ

$ for f in "$1"/*; do fgrep -q "$f" "$2" || echo "$f"; done | xargs rm
これで仕様合ってんのかね。

# .で始まるファイルもあるとこれではまずいが
456 :名無しさん@お腹いっぱい。2011/09/05(月) 11:15:31.47
>>446
grep使うなら"^$line$"した方がいい。
>>452
grep, egrepだと正規表現に使う文字がパス名に含まれると難しい。
しかしfgrepだと部分文字列でマッチしてしまうよ。
448 :名無しさん@お腹いっぱい。2011/09/04(日) 18:47:44.05
コマンドAのstdoutをコマンドBのstdinへパイプで入力、コマンドAのstderrをコマンドCのstdinへパイプで入力を
一発でやることはできますか?
450 :名無しさん@お腹いっぱい。2011/09/04(日) 19:04:13.63
>>448

(com_A | com_B) 2>&1 | com_C
455 :名無しさん@お腹いっぱい。2011/09/05(月) 11:02:57.64
[[ は bash 特有の機能じゃなくて ksh 由来だったかと。
それはそうと、/bin/sh が bash な環境しか使ったことない人は
どれが bash 特有の機能なのかなんかぜんぜん知らないし気にしてないというのが実情。
458 :名無しさん@お腹いっぱい。2011/09/05(月) 12:41:05.07
>>455
一応そういう人を対象(?)にbashの固有の機能を使わないように書くガイドが
debianのマニュアルの中にあった気がする
457 :名無しさん@お腹いっぱい。2011/09/05(月) 11:24:55.01
SUS的には[[は予約語で、動作は未定義。
同様のものにfunction selectがある。

SUS定義の展開系では古典shに
~username
$(command)
$((expression))
が加わってる。

http://pubs.opengroup.org/onlinepubs/009695399/
http://pubs.opengroup.org/onlinepubs/009695399/idx/shell.html
をテンプレに加えたいな。
459 :名無しさん@お腹いっぱい。2011/09/05(月) 13:13:38.31
まあDebianの場合bash依存を減らすのに一番の方法は
ガイドとか読むよりも、まずdashで書き始めることなんだろうけどな
460 :名無しさん@お腹いっぱい。2011/09/05(月) 14:00:50.35
Ubuntu のサイトだけど
https://wiki.ubuntu.com/DashAsBinSh

考えたくない人は
$ sudo dpkg-reconfigure dash

/bin/sh を /bin/bash のシンボリックリンクへ
465 :名無しさん@お腹いっぱい。2011/09/05(月) 15:54:21.01
ほとんどのユーザがしているってこれからもそうとは限らないのでは?
そもそもdashを採用したのはDebianでは現行のsqueezeからだし。
デフォルトではそうなっているっていう事実は考慮すべき。
466 :名無しさん@お腹いっぱい。2011/09/05(月) 22:33:21.16
素人の私に教えてください。
シェル内で scriptコマンド使ったら、
そこでexitで抜けるまでシェル止まってしまうんですが、

script
色々処理
exit

ってシェル内でうまく処理する方法ってないの?
468 :名無しさん@お腹いっぱい。2011/09/06(火) 00:26:39.23
>>466
"&" でscriptコマンドをバックグラウンド実行させればいいのでは?

script &
色々処理
exit

ただしこの場合、scriptコマンドが投げっぱなしになるので、

・scriptコマンドの終了値を取得したい場合
・最終的にscriptコマンドの終了を待ってから呼び出し元のシェルスクリプトを終了したい場合

こういう状況なら少し工夫が必要だと思う
471 :名無しさん@お腹いっぱい。2011/09/06(火) 02:43:49.75
>>468
バックグラウンドで実行すべきはいろいろな処理の方だろ。
scriptは対話的に使うものだから。
467 :名無しさん@お腹いっぱい。2011/09/05(月) 22:41:10.03
同じではないが、近い方法でなら
exec >foo 2>&1
とかあるが。
469 :名無しさん@お腹いっぱい。2011/09/06(火) 00:53:40.00
帰宅途中につきスマホしかないので試してないけど

script script.log << EOF
色々処理
exit
EOF

とできた気がする
472 :名無しさん@お腹いっぱい。2011/09/06(火) 06:43:26.83
>>468 >>469
馬鹿ばっか
487 :名無しさん@お腹いっぱい。2011/09/08(木) 13:40:29.79
>>468さんのやり方だと、色々処理の中での出力がログに出ないような・・・
>>469のやり方で、うまくいきました

> ・最終的にscriptコマンドの終了を待ってから呼び出し元のシェルスクリプトを終了したい場合
そうですね、色々処理の終了を待ってくれはしませんね

シェルスクリプトの中で、scriptコマンドを使ってログを取りつつ、何らかのコマンドの
実行結果のログを取って、それらのコマンドの終了後、scriptコマンドをexitで抜ける、
という作業をうまく行うやり方って、あるのかな?
exitで抜けた後に、取られたログをgrepとかで解析したりしたい

いま似たような事をしているシェルスクリプトは、例えばftpのログはリダイレクトさせて
ログに吐かせ、SQL*Plusの実行時はspoolでログに吐かせ、といちいちコマンド単位に
別々の方法でログに出力させて、一式集めたうえで解析しているのですが、
それをscriptコマンドで統一的に行うことができればなあと思いました
492 :名無しさん@お腹いっぱい。2011/09/09(金) 07:44:48.75
>>487
昔ながらの方法:

#!/bin/sh
exec 3>stdout.log
# stdoutをfd3に切り替える
exec 1>&3
exec 4>stderr.log
# stderrをfd4に切り替える
exec 2>&4
echo "ftp:"; echo "ftp:" 1>&2
echo "ftp log"; echo "ftp error" 1>&2
echo "sql:"; echo "sql:" 1>&2
echo "sql log"; echo "sql error" 1>&2
# 切り替えを復帰してfd3とfd4をクローズ
exec 3>&1 3>&-
exec 4>&2 4>&-
493 :名無しさん@お腹いっぱい。2011/09/09(金) 08:17:56.47
>>492
嘘書くな。

最後の2行で stdoutとstderrが復帰できてない。

あらかじめ fd1 fd2 を execで複製しておいてそれを復帰するべき。
494 :名無しさん@お腹いっぱい。2011/09/09(金) 11:31:29.30
>>493
なんか丁寧に書こうとして失敗してたね…

#!/bin/sh
exec 3>&1 4>&2 1>stdout.log 2>stderr.log
echo "ftp:"; echo "ftp:" 1>&2
echo "ftp log"; echo "ftp error" 1>&2
echo "sql:"; echo "sql:" 1>&2
echo "sql log"; echo "sql error" 1>&2
exec 1>&3 3>&- 2>&4 4>&-
echo "return"
echo "error return" 1>&2
495 :名無しさん@お腹いっぱい。2011/09/09(金) 13:58:09.43
>>487
scriptでやろうとしたり、>>494のような努力をするよりも、
TeraTermとかでログとって、まとめて取れたログをPC上で
解析すんのが、ぶっちゃけ一番簡単じゃね?
496 :名無しさん@お腹いっぱい。2011/09/09(金) 14:21:02.01
>>487
というか、その何らかの処理ってのをまとめて関数にしてしまえばすむ気がするのだが。
俺が勘違いしてるのかな?
475 :自動再起動2011/09/07(水) 06:41:54.75
AppleScript スレ
http://hibari.2ch.net/test/read.cgi/mac/1256127156/l50
の586で尋ねたことと同じ動作をシェルスクリプトでできないか質問.

Mac で落ちたアプリ (TeamViewer を想定) を自動的に起動して「隠す」スクリプト.Ruby 可.回答待ってます.
476 :名無しさん@お腹いっぱい。2011/09/07(水) 07:45:05.72
ここよりもMac板のが詳しいんじゃないかな

Mac OS XをUnixとして使ってる人の為のスレ 16
http://hibari.2ch.net/test/read.cgi/mac/1302132772/
477 :自動再起動2011/09/07(水) 17:03:35.86
>>476
Thanks! そういうスレがありましたね.でもしばらくはここで募集します.
open -g は使うと思うので,鍵は「このアプリは起動中?」を確かめるコマンドじゃないかと考えてる.


478 :名無しさん@お腹いっぱい。2011/09/07(水) 17:14:20.10
>>477
>このアプリは起動中?
普通はpgrepなんだけど
$ which pgrep
/opt/local/bin/pgrep
標準じゃなかったorz
479 :名無しさん@お腹いっぱい。2011/09/07(水) 23:13:26.12
>>477
launchサービスでコントロールしなよ。
484 :自動再起動2011/09/08(木) 12:33:32.60
>>479
なんのことかと思えば,Mac の launch services というやつね
http://developer.apple.com/library/mac/#documentation/Carbon/Conceptual/LaunchServicesConcepts/LSCIntro/LSCIntro.html
ぱっと見た限り,あるアプリから他のアプリその他を開くもののように見える.
質問した動作は,シェルスクリプトでできる範囲外ってことことなのかなあ.
486 :名無しさん@お腹いっぱい。2011/09/08(木) 12:59:00.95
>>484
http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man5/launchd.plist.5.html

> 質問した動作は,シェルスクリプトでできる範囲外ってことことなのかなあ.

専用のデーモンがいるからそれ使え。
490 :自動再起動2011/09/08(木) 23:25:14.75
>>479 >>486 の回答はありがたいが,勉強不足で理解できてません.
ちなみにUNIXシェルスクリプト逆引き大全333の極意の243番に
「特定のコマンドが実行されているかどうか調べる」
というのがある.それが何かは知らないが,
この場合,Macのアプリは「コマンド」には該当しないということですかね.
もし該当するならすぐ答えが出そうなものだから.
491 :自動再起動2011/09/08(木) 23:32:52.83
おっと失礼.>>486 のリンクがおかしくて,今まで OS X Developer Library の Getting Started
に飛んでいた.いま,再びクリックしたら具体的な項目に飛べた.
Thanks a lot! 読んでみます.
480 :名無しさん@お腹いっぱい。2011/09/08(木) 12:10:12.57
$ EXPR="echo \"scale=2;8 / 10\" | bc"
$ PERCENT=`${EXPR}`
$ echo ${PERCENT}
の結果が
"scale=2;8 / 10" | bc
って出力される

.80
って出力を得たいんだけど、どこ直せば良いか教えてください。
482 :名無しさん@お腹いっぱい。2011/09/08(木) 12:26:00.96
>481
$ EXPR="echo \"scale=2;8 / 10\" | bc"
$ PERCENT=eval ${EXPR}
"scale=2;8 / 10" | bc
$ echo ${PERCENT}
"scale=2;8 / 10" | bc

こうなっちゃいました。
なんか間違ってますか?
483 :名無しさん@お腹いっぱい。2011/09/08(木) 12:29:48.70
>>482
PERCENT=`eval ${EXPR}`
497 : 忍法帖【Lv=3,xxxP】 2011/09/11(日) 22:52:35.33
awk(種類は問いません。インストールするので)で二つの表の処理したいと思っています。
表1
bad.com a3
ddfa.net a5
zdf.sj a13
aaa.com a222
表2
aaa.com sd
zdf.sj tt
bad.com tt
ddfa.net sd
処理結果の表
bad.com tt a3
ddfa.net sd a5
zdf.sj tt a13
aaa.com sd a222
フィールド3の数字を昇順にソートした表にして、表2をフィールド2を挿入したい。
※ワンライナーのPerlでも参考までにお願いします。
498 :名無しさん@お腹いっぱい。2011/09/11(日) 22:59:20.03
>>497
表1のフィールド1は、表2のフィールド1に絶対に存在すんの?
499 : 忍法帖【Lv=3,xxxP】 2011/09/11(日) 23:02:41.01
>>498
> 表1のフィールド1は、表2のフィールド1に絶対に存在すんの?
できれば、絶対存在しない場合の方が望ましいです。
存在しない処理のその項目には不明だかとか、そんな感じで処理されるとありがたいです。
500 :名無しさん@お腹いっぱい。2011/09/11(日) 23:27:21.27
>>497
$ cat tab1.txt
bad.com a3
ddfa.net a5
zdf.sj a13
aaa.com a222
$ cat tab2.txt
aaa.com sd
zdf.sj tt
bad.com tt
ddfa.net sd
$ cat awk.sh
#!/bin/sh
while read LINE
do
col1=`echo $LINE | cut -d ' ' -f 1`
col2=`echo $LINE | cut -d ' ' -f 2`
coln=`echo $col2 | sed s/^a//`
coltmp=`grep $col1 tab2.txt`
if [ 0 != $? ]; then
newcol='-'
else
newcol=`echo $coltmp | cut -d ' ' -f 2`
fi
echo $coln $col1 $newcol $col2
done < tab1.txt | sort -n | cut -d ' ' -f 2,3,4
501 :名無しさん@お腹いっぱい。2011/09/11(日) 23:30:06.39
>>500
わざとやってんだろw
503 :名無しさん@お腹いっぱい。2011/09/11(日) 23:41:39.60
>>500
あ〜あ、先に書かれちゃったw でも一応書いておこうっと。。。
ただ、表1のフィールド1が表2のフィールド1に存在することが前提だから
ダメだけど

$ paste -d" " <(sed 's/[ \t]\+/ /g' 02.tbl | sort) <(sed 's/[ \t]\+/ /g' 01.tbl | sort) | cut -d" " -f1,2,4 | sort -t" " -k 3.2 -n
504 :名無しさん@お腹いっぱい。2011/09/11(日) 23:44:55.73
>>500
awk or Perlでお願いします。
506 :名無しさん@お腹いっぱい。2011/09/11(日) 23:49:27.32
>>500,503
ここはシェルスクリプトスレだから…って思ってたら、やっぱりこうなったかw
自分も書こうと思ったけど、やらなくてよかったわ。
正直ソートはsortコマンドに投げたほうが良さそうだと思うんだ。
仕様で表1のフィールド2が重複するならawkだけだと面倒になる。
507 :名無しさん@お腹いっぱい。2011/09/12(月) 00:17:10.38
>>506に答えてくれないから分からないけど外部コマンドも使って重複してても動くように書いた。

awk 'file != FILENAME { file = FILENAME; table++ }
table < 2 { t[$1] = $2; next }
{
  n = $2; gsub(/[^0-9]/, "", n)
  x = ($1 in t) ? t[$1] : "表2に無いよ"
  print n, $1, x, $2
}' 表2 表1 | sort -n | sed 's/[^ ]* //' >処理結果の表

どのawkでも動く。動作未確認。sortに-k0が要るかも。
514 :名無しさん@お腹いっぱい。2011/09/14(水) 00:22:35.90
>>497
亀レスですが perl で、こんなんどうでしょう?
表1を逆にしてハッシュ%cに、表2は%dにそれぞれ突っ込んでます。

perl -0777 -e '

%c=(reverse split(/\s+/,<>));

%d=(split(/\s+/,<>));



foreach $k(sort {($a=~/(\d+)/)[0]<=>($b=~/(\d+)/)[0]}keys %c)

{print "$c{$k} $d{$c{$k}} $k\n"}' tab1.txt tab2.txt


実行結果
bad.com tt a3
ddfa.net sd a5
zdf.sj tt a13
aaa.com sd a222
508 :名無しさん@お腹いっぱい。2011/09/12(月) 00:41:27.03
勉強になるな

a222だのa13だのって、ソート無理じゃね?と思ってたが、こういうひと手間尊敬するわ
510 :名無しさん@お腹いっぱい。2011/09/13(火) 23:03:39.63
バイナリエディタの無い環境で、高々30数バイトのために
インストールするのが面倒だったから、下のようなスクリプトを書いた

#!/bin/bash
IFS=
printf "${*/#/\x}"

引数に並べた1バイトのヘキサを、バイナリに変換するだけなんだが
${*/#/\x} ← こいつがbash依存なんだよね
他の環境だったらどうしたらいいか、賢いやり方が思いつかないのだけど
どういった方法があるかな?bash固有の機能を使わないようにしたい
511 :名無しさん@お腹いっぱい。2011/09/13(火) 23:43:36.25
いちばんどこでも使えそうなのはawkかな
512 :名無しさん@お腹いっぱい。2011/09/13(火) 23:56:26.00
for i in "$@"
do
printf "\\$(printf "%o" 0x$i)"
done
ってのはPOSIX shなら動くと思う
513 :名無しさん@お腹いっぱい。2011/09/14(水) 00:21:09.75
マジな話ポータビリティにこだわるのって本当に意味あるの?
517 :名無しさん@お腹いっぱい。2011/09/14(水) 00:45:39.24
>>513
こだわる心がけそのものについては、殊勝であり意味はあるが、だがその行為には価値が無い
518 :名無しさん@お腹いっぱい。2011/09/14(水) 00:49:48.76
>>511 初めに考えたけど、これを思いついたから。awkも亜種が多いし

>>512
そういえばprintfはどのシェルでも内部コマンドで用意されてたっけ
1つずつ処理するのは時間がかかりそうって思ったんだが、そうでもないのか

>>513 こだわってる訳じゃなく手元にbashの無い環境もあったので

最終的に入力がワードサイズのリトルエンディアンだったことに気が付いて下のようになった

IFS=\
printf "`echo " $*" |sed 's/ \([^ ]*\) \([^ ]*\)/\\\\x\2\\\\x\1/g'`"

皆さんどうもありがとう
521 :名無しさん@お腹いっぱい。2011/09/14(水) 08:04:47.40
>>513
人によってはあるんじゃない?
522 :名無しさん@お腹いっぱい。2011/09/14(水) 13:13:00.93
>>513
30代の漏れは大学自体は NEWS や SUNOS / Solaris, FreeBSD, Linux
と混沌とした混在環境だったからポータビリティに気を使ってたなぁ。
よく perl に逃げてた覚えが...
553 :名無しさん@お腹いっぱい。2011/09/16(金) 02:34:05.36
j jobs
k kill
l ls
とか、aliasで短縮している。
>>513
> マジな話ポータビリティにこだわるのって本当に意味あるの?
捨てプログラムなら何でも良いし、使用頻度低くて危険ではないプログラムならとりあえず自分の環境で動けばいいんじゃないの。
あとLinuxを使いつづけているとオリジナルのプログラムって自然と増えていくし、半年以上経ったプログラムをまじめに読み返したくないから
書きたい衝動のときにやれることはやっておくのがあとあと楽。
516 :名無しさん@お腹いっぱい。2011/09/14(水) 00:44:40.04
awkだとこれでいいのかな
awk 'BEGIN{for(i=1;i<ARGC;++i)printf("%c",int("0x"ARGV[i]))}'
519 :名無しさん@お腹いっぱい。2011/09/14(水) 00:52:13.62
>>516
文字列を数値に直すとき0xを見て16進数と解釈するのはgawkの拡張じゃなかったかな。
523 :名無しさん@お腹いっぱい。2011/09/14(水) 15:51:33.93
Perlってひとつの環境のバージョン違いぐらいしか基本的にないから、そういうときは何気に便利よね
524 :名無しさん@お腹いっぱい。2011/09/14(水) 22:38:18.78
機能に過不足があっても何とか代替手段を編み出せるOSコマンド群と、
モジュール不足で機能が欠損するperl環境を比較すると、perlもそんなに
便利じゃない

原理的OSコマンドセットかGNUのbinutilsかって違いよりも大きいだろ
530 :名無しさん@お腹いっぱい。2011/09/15(木) 00:47:20.88
>>524
uname の結果見て if 文書きまくって OS 毎にちゃんと動くようにするのは結構辛いぜ?
# 昔 echo -n するのに Solaris ならわざわざ /usr/ucb/echo って指定したり
# とか面倒な事してましたよ。

perl の機能欠損? /bin/sh だけだと機能欠損あるから grep/sed/awk とかを
使ってるわけで、 perl からだって grep/sed/awk とかを呼び出ししても良いわけだし。
何でもかんでも perl で書こうとしてるから不便に感じてるのでは。
525 :名無しさん@お腹いっぱい。2011/09/14(水) 22:46:26.27
シェルスクリプトのちょっとした補完(ここではバイナリ出力)
という目的でLL使おうって話なんだから、
モジュールやらなんやらまで必要なプログラムの話じゃないだろ
526 :名無しさん@お腹いっぱい。2011/09/14(水) 23:33:29.77
「LL」っていう定着していない略語使う奴に限ってシェルスクリプトを使いこなせていない、の法則。
531 :名無しさん@お腹いっぱい。2011/09/15(木) 03:01:04.51
llと言えば 'ls -l' のエイリアスかなと思う。
533 :名無しさん@お腹いっぱい。2011/09/15(木) 10:04:28.95
>>531
それこそ定着していない。
534 :名無しさん@お腹いっぱい。2011/09/15(木) 10:54:34.18
>>531
”ll” とかだっせーw
537 :名無しさん@お腹いっぱい。2011/09/15(木) 16:28:07.16
llって、どのへんが起源なんだろうな

実現方法がOSによって違うからビビる
538 :名無しさん@お腹いっぱい。2011/09/15(木) 17:22:52.99
ls -l ってわざわざ別名でaliasするほどのものかなあ
よく使うオプションをls自体にaliasしておいて、時々使うものは逐次指定でよくない?
557 :名無しさん@お腹いっぱい。2011/09/17(土) 02:13:08.53
>>538
そう思うけど過去にRed HatだったかVineだったかで/etc/profileにデフォルト設定されてたのよ。
la='ls -a' とかな。
変な癖ついちゃうと後々面倒だから使わなかったけど。
560 :名無しさん@お腹いっぱい。2011/09/19(月) 16:43:26.44
>>557
そうなのか…そういう鳥があったなら仕方ない。
俺はその辺から入った身じゃないけど、その辺から入ってたら確かにaliasしてたかも知れんな。
539 :名無しさん@お腹いっぱい。2011/09/15(木) 17:28:15.73
わざわざっていうか、OS 側でデフォルトで設定してあったりする。
541 :名無しさん@お腹いっぱい。2011/09/15(木) 18:23:27.91
aliasで設定しているOSもあれば、llというコマンド(実体はlsのリンクだが)で提供しているOSもある
542 :名無しさん@お腹いっぱい。2011/09/15(木) 18:26:06.10
>>541
後者は知らなかったな。
なんてOS?
552 :名無しさん@お腹いっぱい。2011/09/15(木) 21:36:49.17
>>542
http://h20000.www2.hp.com/bc/docs/support/SupportManual/c02261048/c02261048.pdf
↑のHP-UX 11i v3のマニュアルによると

ll is equivalent to ls -l (ell)
The shorthand notations are implemented as links to ls.
てことだ
543 :名無しさん@お腹いっぱい。2011/09/15(木) 18:31:34.68
/etc/profileや /etc/profile.dにある設定って余計なお世話だから、
OS新規インストール直後に即攻で消すわ。
おまえらもそうだよな?
547 :名無しさん@お腹いっぱい。2011/09/15(木) 18:50:05.32
使うサーバの数多いし自分だけで使うわけじゃないから
なるべくツルシの状態で使うようにしてる。
548 :名無しさん@お腹いっぱい。2011/09/15(木) 19:01:30.40
商用OSかフリーOSかで違うなぁ。
商用OSなら/etc/profileとか考えられて設定されてるんだろうから、消さない。
フリーOSの場合、メンテナなりパッケーじゃなりの個人的趣味が /etc/profileに
書かれてたりするから、趣味の押しつけ拒否ですぐに消してしまう。
549 :名無しさん@お腹いっぱい。2011/09/15(木) 19:12:16.22
商用でもいーかげんな設定はあるし、
フリーでも考えて設定してあるのもあるし、
そんなの一概には言えんよ。
550 :名無しさん@お腹いっぱい。2011/09/15(木) 20:02:48.99
AIXやSolarisだと、いい加減というか、ほとんど何も設定してないでしょ。
HP-UXだと、Terminalの追加設定がprofileだったかに書かれてて、うかつに置き換えたりすると、「あれ?キーがきかねーぞ」とか言われたりするけど。
555 :名無しさん@お腹いっぱい。2011/09/16(金) 11:16:14.80
aliasでやってんのかコマンドでやってんのかって違いは、下手するとシェルスクリプトの実行結果にの影響を与えるものだよ

cronで動かしてるシェルスクリプトとかで
556 :名無しさん@お腹いっぱい。2011/09/16(金) 11:49:39.54
スクリプト内で短縮形を使うとかありえないw
あと、特に意味もなく使う相対パスも。
558 :名無しさん@お腹いっぱい。2011/09/17(土) 08:36:48.69
だからメンテナなりパッケージャなりの個人的趣味の /etc/profileは
即攻で消すべきなんだよ。
559 : 忍法帖【Lv=5,xxxP】 2011/09/17(土) 11:31:09.22
いきなり消すことないじゃん。
インストール後に速攻rsyncで/etcと$HOMEをコピーして、当分の間残しておく。
561 :名無しさん@お腹いっぱい。2011/09/28(水) 23:09:14.82
./test.sh "a a" "b b" "c c"
とスペースありの
引数を複数指定してシェルスクリプトを起動して、
さらに、
test.sh
では、
./test2.sh "a a" "c c"
と引数 "b b" を削って、別のシェルスクリプトを起動します。

初めの test.sh に渡される引数の数が不定で、
"b b"がどこに現れるかも不定の時、
引数 "b b" だけを抜いて、
test2.sh の引数としたいのですが、どうしたらできますでしょうか?

562 :名無しさん@お腹いっぱい。2011/09/28(水) 23:19:04.60
>>561

#!/bin/bash

argv=("$@")
for ((i=0; i < $#; i++)) {
case "${argv[i]}" in 'b b') unset argv[i];; esac
}

./test2.sh "${argv[@]}"
563 :名無しさん@お腹いっぱい。2011/09/28(水) 23:26:47.27
>>562
ありがとうございます!
が、ホントすみませんが、shでお願いします。
564 :名無しさん@お腹いっぱい。2011/09/28(水) 23:36:05.08
>>561

#!/bin/sh

n=$#
while [ "$n" -gt 0 ]; do
if [ "$1" != 'b b' ]; then
set "$@" "$1"
fi
shift
n=`expr $n - 1`
done

./test2.sh "$@"
565 :名無しさん@お腹いっぱい。2011/09/28(水) 23:43:24.70
>>564
ありがとございます!
set "$@" "$1"
にはやられました。
ホント助かりました。
精進します。
568 :名無しさん@お腹いっぱい。2011/09/29(木) 18:34:51.04
>>564
引数の中に -a -b -c とか含まれていると誤動作する。

set -- "$@" "$1"
だな。
常に set -- にする習慣を。
567 :名無しさん@お腹いっぱい。2011/09/29(木) 17:11:36.86
いいかい、setの活用は set set set。どの setかは文脈で判断するんだ。
ただし、三単現の場合は setsになるので、これも手がかりになる。
569 :名無しさん@お腹いっぱい。2011/10/09(日) 13:58:18.17
引数として渡された複数のテキストファイルに対して
各ファイルの冒頭に、ファイルのフルパス名を書いた簡単なヘッダを付け
それらをcatのように連結させて標準出力したいのですが、どんな感じでやれば良いのでしょうか
570 :名無しさん@お腹いっぱい。2011/10/09(日) 14:09:57.68
#! /bin/sh
for UNKO in `echo $*`
do
echo "Header: ${UNKO}"
cat ${UNKO}
echo "manko"
done
572 :名無しさん@お腹いっぱい。2011/10/09(日) 14:27:36.32
>>570
ありがとうございます、とりあえずこれでも充分です
フルパスにする方法は自分で調べますね
573 :名無しさん@お腹いっぱい。2011/10/09(日) 14:48:25.58
>>570
フルパス以前の問題として、

in `echo $*` ってギャグかよ! スペース入りファイル名で誤動作しまくり。
in "$@" が常識。あるいは、for文では省略すると in "$@" の意味になる。
574 :名無しさん@お腹いっぱい。2011/10/09(日) 14:53:46.23
自分は与えられたファイルのフルパスを調べるとき、>>570に倣うなら、

FILENAME=`basename ${UNKO}`
PATHWORK=`dirname ${UNKO}`
FILEDIR=`cd ${PATHWORK}; pwd`
FULLPATH=${FILEDIR}/${FILENAME}

みたいな感じに順々にやってるけど、なんかサクッと取得する方法って、ある?
578 :名無しさん@お腹いっぱい。2011/10/09(日) 17:08:34.27
>>573
ってことは、相対パスの場合

for S do
echo "<<<<< ${S} >>>>>"
cat ${S}
done

が最適解ですね、ありがとうございます
579 :名無しさん@お腹いっぱい。2011/10/09(日) 17:16:19.97
>>578
なぜcatの方はクォートしないし
580 :名無しさん@お腹いっぱい。2011/10/09(日) 17:18:00.09
>>579
あう、>>570 を改変したためクォートしないまま残ってました
575 :名無しさん@お腹いっぱい。2011/10/09(日) 15:04:17.56
FreeBSDやUbuntuにはデフォでrealpathが入ってたような気がするし
Linux系列ならreadlink -fでおk
583 :名無しさん@お腹いっぱい。2011/10/09(日) 18:41:50.45
>>575
readlinkか…何気に今日最大の収穫だわい
581 :名無しさん@お腹いっぱい。2011/10/09(日) 17:42:37.61
doの前に;
584 :名無しさん@お腹いっぱい。2011/10/09(日) 19:08:49.76
>>581-582
ってことは、こんな感じですか?

for NAME; do
echo "ヘッダ${NAME}"
cat "-- ${NAME}"
done
582 :名無しさん@お腹いっぱい。2011/10/09(日) 17:55:48.05
相対パスの場合、
ファイル名として -n とか -v とかが含まれていると
cat "${S}"
が面白いことになるw
586 :名無しさん@お腹いっぱい。2011/10/11(火) 08:05:18.23
ボーンで、配列って使える?くぐってもわからんかった。
588 :名無しさん@お腹いっぱい。2011/10/11(火) 08:18:01.32
>>586
工夫すれば使える。
587 :名無しさん@お腹いっぱい。2011/10/11(火) 08:16:38.19
bashとかじゃなきゃ無理じゃなかった?配列っぽく変数を扱うことは出来るが
589 :名無しさん@お腹いっぱい。2011/10/11(火) 09:15:05.14
とつぜんだがちょっと関数書いたので貼ってみる

gengou(){
TMP_LANG=$LANG ;
LANG=ja_JP.UTF-8 ;
export LANG ;
case $1 in
[0-9]*)
echo $(if test $1 -gt 1988 ;then echo '平成'$(expr $1 - 1988 ;) ;
elif test $1 -gt 1925 ;then echo '昭和'$(expr $1 - 1925 ;) ;
elif test $1 -gt 1911 ;then echo '大正'$(expr $1 - 1911 ;) ;
elif test $1 -gt 1867 ;then echo '明治'$(expr $1 - 1867 ;) ;
else echo '西暦'$1 ;
fi ;)'年' ;
: ;;
[[:alpha:]])
echo "USAGE $0 1" ;;
esac ;
LANG=$TMP_LANG ;
}

どうかな?明治以降で申し訳ないが
688 :名無しさん@お腹いっぱい。2011/10/27(木) 02:08:45.38
今時学校のレポート課題にシェルスクリプトを書けってのはそんなにないんじゃない?
>>589みたいに何の役にも立たないスクリプトなら見ただけで学校の課題って分かるけど。
590 :名無しさん@お腹いっぱい。2011/10/11(火) 11:07:07.14
行末の;がキモ過ぎ
595 :名無しさん@お腹いっぱい。2011/10/11(火) 13:38:30.40
>>590-594
みなさんどうもありがとう。
これでレポートが出せそうです。
593 :名無しさん@お腹いっぱい。2011/10/11(火) 13:12:47.84
ボーンで使えない $( ) とか [[:alpha:]] は使うべきじゃない。

逆に、ボーン対応しなくていいなら、遅いexpr使わずに $(( )) を使うべき。
594 :名無しさん@お腹いっぱい。2011/10/11(火) 13:29:44.63
case文で [0-9]*) で判定してるけど、3hoge とかでもマッチするぞ。
正規表現と勘違いしてる?

case文で場合わけするなら、残りは *) でデフォルトにするべき。

シェル関数内の $0 はシェル関数名を表さない。(もとのシェルスクリプト名になる)
なので、USAGE $0 とか書いてるのはおかしい。
596 :名無しさん@お腹いっぱい。2011/10/15(土) 07:49:31.32
「もし、当該ファイルに、指定した正規表現が含まれているなら、次の処理を実行する」
というような時、どのように書けばいいでしょうか?
597 :名無しさん@お腹いっぱい。2011/10/15(土) 08:42:17.08
>>596

if egrep '正規表現' file > /dev/null 2>&1; then
次の処理
fi
599 :名無しさん@お腹いっぱい。2011/10/15(土) 09:18:58.77
>>598
grep の -q や -s オプションはバージョンによって使えなかったり
挙動が異なったりするので、-q -s を使わずに /dev/null にリダイレクト推奨。

>>597
thenの前に ;
600 :名無しさん@お腹いっぱい。2011/10/15(土) 16:02:44.00
>>597,598,599
ありがとうございました
598 :名無しさん@お腹いっぱい。2011/10/15(土) 08:59:12.02
grep -qs -e regexp file && hogehoge
601 :名無しさん@お腹いっぱい。2011/10/17(月) 12:52:21.92
$PATHに、とあるパス($PWD/bin)を追加したいのですが、
$PATHに存在しない場合だけ追加したいです。
それで、あるパスが$PATHに含まれているかどうかを調べるにはどのような方法がいいでしょうか。

if `echo $PATH | grep "$PATH/bin"`; then
 export $PATH=$PATH/bin:$PATH
fi

こんなのでいいでしょうか。
602 :名無しさん@お腹いっぱい。2011/10/17(月) 13:48:59.00
>>601
内部コマンド(case文)だけでやった方が良い

case ":${PATH}:" in
*:"$PWD/bin":*)
;;
*)
PATH=$PWD/bin:$PATH
;;
esac
603 :名無しさん@お腹いっぱい。2011/10/17(月) 14:49:24.55
>>602
かっこいい!さんくすです。
604 :名無しさん@お腹いっぱい。2011/10/17(月) 21:03:41.31
windowsサーバのMRTGをunixで作ってます
unixサーバはMRTG出来てるんだけど、シェルスクリプト使って値取得してます
unixに合わせて欲しいと言われたのでスクリプトやろうとしてますがプログラムほとんど分からなくて困ってます
メモリとcpuとハードが対象で、メモリは%表示でcpuと一緒に一つのグラフに載せてて、MIB取得とグラフ表示は出来てます
出来てるunixのスクリプトの中身を見るとMIB値を取得して変数に入れて除算とかしてるようです
どなたか助けてください
606 :名無しさん@お腹いっぱい。2011/10/18(火) 00:05:25.33
>>604
監視対象が Windows で値をとってグラフにする側が UNIX ってことでしょ?
別に相手が UNIX だろうが Windows だろうが SNMP で MIB の値をとってくる
ことに変わりはないと思うぞ。

もちろん OID が違うだろうから OID のところだけ変えてやればいいだけなんじゃないか?
# 軽くググった感じでは Windows XP の CPU 使用率とかの OID がでてくるけど。
607 :名無しさん@お腹いっぱい。2011/10/18(火) 08:18:57.55
>>605
>>606
そうです。windowsのMIB値取得して、unixでグラフ表示です
スクリプトの中身もsnmpwalkでMIB値を変数に入れて計算させてるようなので、MIB値変えてやってみます
ありがとうございます
609 :名無しさん@お腹いっぱい。2011/10/18(火) 23:16:35.95
>>604です
何度も申し訳ないのですが、助けてください
OIDを変えたりいろいろやってみたのですが、いまいちうまく動いてくれません。
下記がまともに動いているunixのスクリプトです
※一度に入らないのでいくつかに分けます

##!/bin/sh

SNMPWALK="/usr/local/bin/snmpwalk"

COMMUNITY="${1:-public}"

HOST="${2:-localhost}"

CPU1=`"${SNMPWALK}" -v 2c -t 0.1 -c "${COMMUNITY}" "${HOST}"
ssCpuUser.0 2> /dev/null | awk '{print
$4}' 2> /dev/null`

X=`expr "$CPU1" : '\([0-9][0-9]*\)'`
if [ $CPU1 != $X ]; then
echo "0";echo "0" ; exit;
fi

CPU2=`"${SNMPWALK}" -v 2c -t 0.1 -c "${COMMUNITY}" "${HOST}"
ssCpuSystem.0 | awk '{print $4}'`

USAGE1=`echo "( ${CPU1} + ${CPU2} ) * 10" | bc`
610 :名無しさん@お腹いっぱい。2011/10/18(火) 23:17:44.00
>>609の続きです

MEM1=`"${SNMPWALK}" -v 2c -t 0.1 -c "${COMMUNITY}" "${HOST}"
memTotalReal.0 | awk '{print $4}'`
MEM2=`"${SNMPWALK}" -v 2c -t 0.1 -c "${COMMUNITY}" "${HOST}"
memAvailReal.0 | awk '{print $4}'`

MEM_FREE=`echo "scale=3 ; ( "${MEM2}" / "${MEM1}" ) * 1000" | bc | cut -d\. -f1`

USAGE2=`expr 1000 - "${MEM_FREE}"`

if [ "${USAGE1}" -lt 0 -o "${USAGE1}" -gt 1000 ]; then
USAGE1="0"
fi

if [ "${USAGE2}" -lt 0 -o "${USAGE2}" -gt 1000 ]; then
USAGE2="0"
fi

echo "${USAGE1}"
echo "${USAGE2}"

exit 0
611 :名無しさん@お腹いっぱい。2011/10/18(火) 23:47:27.26
>>609がCPU処理
>>610の最初がメモリ処理
最後がifでの分岐と最終結果の表示になってます

CPUについてはOIDを 「hrProcessorLoad」 にしたのですが
どうやら取得できているようです

メモリについては 空きメモリ / トータルメモリ * 1000
をやって使用率をパーセント表示させているようです。
ただ、windowsのsnmpだとトータルメモリが一発で取れないため

MEM3=`"${SNMPWALK}" -v 2c -t 0.1 -c "${COMMUNITY}" "${HOST}"
hrStorageSize.5 | awk '{print $4}'`

MEM4=`"${SNMPWALK}" -v 2c -t 0.1 -c "${COMMUNITY}" "${HOST}"
{hrStorageAllocationUnits.5 | awk '{print $4}'`

MEMtotal = "${MEM3}" * "${MEM4}" を追加してトータルメモリを取得してます
同様に使用メモリも算出して
空きメモリ = トータルメモリ - 使用メモリ としてます
そして、最後に 空きメモリ / トータルメモリ * 1000 
で後は使いまわしているのですが、うまくいきません。
そもそもやり方としてはあっているのでしょうか?
617 :名無しさん@お腹いっぱい。2011/10/19(水) 20:28:33.72
>>611
純粋に snmpwalk でこけてるだけでしょ?
snmpwalk 単体で実行して値が取れるところまで頑張ってくれ。
snmp の話でスクリプト関係ない。
板違いなんで一旦終わりの方向で。

板違いだが一応指針だけ。
もう一度 Windows で CPU 使用率とる OID 調べてみろ。
俺が見た限りだと SNMP4NT とやらをインストールして、
.1.3.6.1.4.1.311.1.1.3.1.1.2.1.3 あたりのどっかの値をとるみたいだ。

ちなみにロード(ロードアベレージ)はかなりの確率で君のほしがって
いる値ではないであろうと推測される。
622 :名無しさん@お腹いっぱい。2011/10/19(水) 21:06:20.31
>>617
MIB値が正常に取れてなかったです
今日朝イチでケアレスミスを見つけて、そこ直したらメモリとCPUの%とれました
板違いで本当にすみませんでした
教えてくださりありがとうございます
605 :名無しさん@お腹いっぱい。2011/10/17(月) 21:07:27.04
いや。助けろって言われても俺に具体的に何をしろと?
とりあえずその「出来てるスクリプト」を読んで同じように書けばいいだけのような。
608 :名無しさん@お腹いっぱい。2011/10/18(火) 08:35:04.55
配列を各変数に一度に代入したいのですがどう書けばいいのでしょうか?
イメージとしては
a,b,c=array('a','b','c')
のようなことをしたいです
612 :名無しさん@お腹いっぱい。2011/10/19(水) 00:28:31.23
bcに-lがない。突っ込みたいところはあるけど仕事だろ?じゃあ寧ろ弄らないほうがいい
613 :名無しさん@お腹いっぱい2011/10/19(水) 18:53:11.71
着信したメールをパイプして、Subject: が特定の文字(例えばrequest)なら
本文を標準出力に出すスクリプトを書きたいんですが、考え方が良く分かりません。
ちなみにメールは
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:7.0.1) Gecko/20110929 Thunderbird/7.0.1
MIME-Version: 1.0
To: postmaster@domain.jp
Subject: Test
Content-Type: text/plain; charset=ISO-2022-JP
Content-Transfer-Encoding: 7bit

This is test mail.

-
Subject: が Test で
本文が This is test mail. です。

614 :名無しさん@お腹いっぱい。2011/10/19(水) 19:01:06.40
>>613
procmail 使え、とかそういう話?
615 :6132011/10/19(水) 19:42:40.82
>>614
postfixで返信を考えてるんですが、aliasesでメール内容をスクリプトに
パイプすることはできるんです。
パイプで渡された内容は、引数として扱えるのでしょうか?
618 :名無しさん@お腹いっぱい。2011/10/19(水) 20:38:11.44
>>613
Subject: に Test が含まれるメールのみ、その本文(のみ)を標準出力に出すスクリプト

#!/bin/sh

sed -n '1,/^$/{ /^Subject:/{ /Test/!q } }; /^$/,$p'
619 :名無しさん@お腹いっぱい。2011/10/19(水) 20:40:06.76
>>613
RFCに従ったメールであれば、「ヘッダ部+空行+本文」の構成なので、
本文のみを抜き出したければ、最初の空行以降の文を抜き出してみそ。
620 :名無しさん@お腹いっぱい。2011/10/19(水) 20:46:08.68
>>618 が具体解答書いた後に抽象概念だけ書く >>619 って・・・
623 :6132011/10/19(水) 22:55:23.44
>>619
ありがとうございます。
一行ですむんですか
まだ、しっかり理解できないので、勉強してみます。
630 :名無しさん@お腹いっぱい。2011/10/20(木) 18:31:11.49
考え方の解説として>>619も>>628も有用だよ

そして>>618が読み解けない俺orz
631 :名無しさん@お腹いっぱい。2011/10/20(木) 23:36:53.85
あれじゃマルチパートのメール着たら死亡だけどねえ。
boundary指定のメール来ることも考えるのなら、
専用のモジュール使ってperl, python辺りで書いた方がいいよ。
今は>>613みたいな古典的な形式のメールばかりじゃないからね。
632 :名無しさん@お腹いっぱい。2011/10/21(金) 06:39:13.89
>>625
>>631
元の質問 >>613 は、
システムの遠隔操作等で
「自分で」特定のSubject:(半角英数)のメールを送って操作したいということだから、
SubjectがMIMEエンコードされてたり複数行の場合とか、
マルチパートのメールについては考えなくていい。
633 :6252011/10/21(金) 09:58:20.71
>>632
だんだんとスレチになってきたけど…
User-Agent が Thunderbird だから、エンコードを知らない古の mail コマンドや
telnet コマンドでmail するときのように自分で Subject をゴリゴリ書いてないのが気になります。
「自分で」アラートメールを送らせて監視するシステムっぽいというのは判断できますが
メールクライアントは、そのアプリの判断で MIME エンコードしますよ。charset=ISO-2022-JP だし。
仕事で作ったとなると「日本語のほうが分かりやすいだろ」とかで仕様変更されトラブることも考えられる。

あえて言えば、勘違いさせるサンプルが悪い。そして俺必死すぎ。
635 :名無しさん@お腹いっぱい。2011/10/21(金) 10:26:41.98
>>633
メールクライアントはThunderbirdだと特定できてるのだから、
Thunderbirdは英数文字のみのSubject:をMIMEエンコードしない。
(たとえcharset=ISO-2022-JPでも)
637 :名無しさん@お腹いっぱい。2011/10/21(金) 11:35:22.79
>>632
> 元の質問 >>613 は、
> システムの遠隔操作等で
> 「自分で」特定のSubject:(半角英数)のメールを送って操作したいということだから、

どこにそんなこと書いてあるの?
ちょっとびっくりした。それとも>>613本人なのか?
646 :名無しさん@お腹いっぱい。2011/10/21(金) 14:53:32.27
>>615読めよ。
aliasで| cmdしたいんだろ。
649 :6132011/10/22(土) 08:27:38.00
やっと、sed -n '1,/^$/{ /^Subject:/{ /Test/!q } }; /^$/,$p' の意味が
分かって帰ってきました。なにかお騒がせしてたみたいですいません。
>>618 ありがとうございました。
とりあえず、Subject: は英文のみ、本文は最初の1行のみを有効にするつもりです。
sedはどうも、一般のシェルとは様子が違うようでなかなかわかりにかいですが
Retrun-Pasth: と 本文を変数に代入することって出来ないでしょうか?



650 :名無しさん@お腹いっぱい。2011/10/22(土) 08:35:54.71
>>637 よ、>>649 ↓のカキコ見たかい?
> Subject: は英文のみ、本文は最初の1行のみを有効にするつもりです。

やっぱり質問者は制御メールに関する質問をしていたわけだ。
(メールボックスのフィルターの話じゃない)

読解力のなかった >>637 は謝罪会見開け。
652 :名無しさん@お腹いっぱい。2011/10/22(土) 09:31:23.54
>>649
凝ったことやりたいならperlか何かで書いた方がいいんじゃないの。
655 :名無しさん@お腹いっぱい。2011/10/22(土) 09:44:15.17
>>649
ちょっと時間がないので概念だけ、

sedを使わずに、/bin/shの while read arg1 arg2 でメール全体を行ごとに読んで回す。
case $arg1 で場合分けして、Subject: やRetrun-Path: の時、
arg2の値を変数にコピーして記憶する。
$arg1が空文字( '' )の時はヘッダーの終了なので、
その場で再度 read body ってやると、"$body" にメール本文の最初の1行が入る。
ここで breakでwhileループを中断する。
656 :6132011/10/22(土) 09:48:18.87
>>652
Postfixのaliasが、メールのテキストをパイプで渡すみたいねんですが
シェルにしても、perlにしても標準入力を変数に代入するにはどうすればいいですか?
どうもこのパイプからの入力の扱いが理解できて無いもので
660 :名無しさん@お腹いっぱい。2011/10/22(土) 10:41:04.97
>>655 をコーディングすると、以下になる。


#!/bin/sh

while read arg1 arg2
do
case $arg1 in
Subject:)
subject=$arg2;;
Retrun-Path:)
return_path=$arg2;;
'')
read body
echo "$subject"
echo "$return_path"
echo "$body"
break;;
esac
done

ただし、while文を抜けるとサブシェル問題で変数が元に戻る問題は別途対応のこと。
661 :6132011/10/22(土) 11:01:19.56
>>655 660
なんとなく分かったような
また、しばらくもぐりこんできます。
ありがとう
663 :名無しさん@お腹いっぱい。2011/10/22(土) 14:06:32.88
>>650 粘着キチガイ犬が必死すぎる。www
664 :名無しさん@お腹いっぱい。2011/10/22(土) 14:11:51.76
>>656
> perlにしても標準入力を変数に代入するにはどうすればいいですか?
while (<>) { ... } で $_ に入れる、とか。
http://www.lr.pi.titech.ac.jp/~abekawa/perl/perl_lecture.html
666 :名無しさん@お腹いっぱい。2011/10/22(土) 14:16:40.84
>>650
何ら立証できてないのに、バカがはしゃいで勝ち誇ってる。哀れすぎる。
667 :名無しさん@お腹いっぱい。2011/10/22(土) 14:39:26.40
>>666

>>649 (質問者本人)
> Subject: は英文のみ、本文は最初の1行のみを有効にするつもりです。


この質問者本人からの1文で,完璧なまでに >>666 の敗北が立証されたねw
それとも >>666 は読解力がないから、自分が敗北したことも理解できてないのか?ww
669 :名無しさん@お腹いっぱい。2011/10/22(土) 16:53:00.47
>>656
上のようにstdinを三回舐める時は、
cat > /tmp/foobarbaz$$
/tmp/foobarbaz$$に対する処理
rm -f /tmp/foobarbaz$$
とすればいい。
671 :名無しさん@お腹いっぱい。2011/10/22(土) 17:03:01.10
>>667
精薄哀れすぎる。 www

それだけで制御と決めつけられる単純な思考しか出来ない事を
そんなに必死になってアピールしなくてもいいんだぞ。
624 :名無しさん@お腹いっぱい。2011/10/20(木) 11:20:21.94
結局お礼もらったのは「抽象概念」だけ書いた方じゃないかw
625 :名無しさん@お腹いっぱい。2011/10/20(木) 13:04:59.53
昨今のメールだと、Subject がエンコードされてて 1行じゃ済まない気がしますが…
626 :名無しさん@お腹いっぱい。2011/10/20(木) 17:44:11.90
質問です
シェルで、代入するときに、変数名を可変にすふことは可能でしょうか?

array_$1=$some_value

みたいにして、配列のようにあつかいたいのですが…
627 :名無しさん@お腹いっぱい。2011/10/20(木) 17:51:03.15
>>626
可能。

eval array_$1=$some_value
628 :名無しさん@お腹いっぱい。2011/10/20(木) 17:57:09.43
>>626
Bシェル系に従ったシェルであれば、「左辺変数名決定→変数展開」の順なので、
展開後に左辺変数名として解釈させたければ、evalを付けて実行してみそ。
629 :名無しさん@お腹いっぱい。2011/10/20(木) 17:58:51.92
>>627 が具体解答書いた後に抽象概念だけ書く >>628 って・・・
634 :名無しさん@お腹いっぱい。2011/10/21(金) 10:12:36.43
そういうのは本人が考えることだから
議論してもしょうがない。
639 :名無しさん@お腹いっぱい。2011/10/21(金) 11:45:17.75
「操作する」と「出力する」は全然違うんだが。
640 :名無しさん@お腹いっぱい。2011/10/21(金) 11:57:23.42
>>639
読解力のなさをわざわざアピールしなくていいよw
642 :名無しさん@お腹いっぱい。2011/10/21(金) 12:54:28.16
>>640
「出力する」を「操作する」と誤読したボンクラのレスなど読解する必要は無い。
643 :名無しさん@お腹いっぱい。2011/10/21(金) 13:15:45.03
>>642
「出力する」のは何の為か、って読解力もないのかねw
644 :名無しさん@お腹いっぱい。2011/10/21(金) 14:40:15.35
メールボックスのフィルター捕まえて、
「遠隔操作」って言葉が最初からおかしい。
645 :名無しさん@お腹いっぱい。2011/10/21(金) 14:42:47.56
>>644
えっ?
メールボックスのフィルターの話じゃないんだけど・・
647 :名無しさん@お腹いっぱい。2011/10/21(金) 15:48:23.28
質問者を置いてきぼりにしたくだらない揚げ足取りって、
すっかりこのスレの名物だね。
この板の他のスレではめったにないのに、ここだけは日常的にやってる。
648 :名無しさん@お腹いっぱい。2011/10/21(金) 16:02:35.18
ここだけじゃないだろ
○○システムズ最後の○○ のスレで毎日やってる
651 :名無しさん@お腹いっぱい。2011/10/22(土) 08:51:58.83
バカが必死すぐる。www
662 :名無しさん@お腹いっぱい。2011/10/22(土) 12:48:13.35
>>637 = >>639 = >>642 = >>644 = >>651
の謝罪会見まだぁ??
653 :名無しさん@お腹いっぱい。2011/10/22(土) 09:35:23.36
そういうこと言う奴に限って、「じゃあperlで書いて」と言ったら書けないんだよなw
657 :名無しさん@お腹いっぱい。2011/10/22(土) 10:09:37.85
read使う。
658 :名無しさん@お腹いっぱい。2011/10/22(土) 10:35:08.49
>>655 が投稿した「後」に何の情報も増えてない投稿する >>657 って・・・
668 :名無しさん@お腹いっぱい。2011/10/22(土) 16:49:54.52
捌くメールの数が大したことないなら1パスにこだわらずに、
subject=`sed -n '1,/^$/s/^Subject:\(.*\)/\1/p' "$FILE"`
returnpath=`sed -n '1,/^$/s/^Return-Path:\(.*\)/\1/p' "$FILE"`
body=`sed -n '/^$/,+1p' "$FILE"`
としてもいいんじゃないの?

多い場合は舐めるデータ量より、sedの三回起動のほうが問題になるはず。
670 :名無しさん@お腹いっぱい。2011/10/22(土) 16:58:22.16
1パスの解答 >>660 の後に 3パス(しかも一時ファイル必要)の解答する >>668 って・・・
672 :名無しさん@お腹いっぱい。2011/10/22(土) 17:15:37.83
>>670
必要なかったかね。
仕様では:の後はスペースなくても構わないので、
(その辺は説明せずに)つい書いてしまったわ。
IFSに:を加える修正したほうが良かっただろうね。
673 :名無しさん@お腹いっぱい。2011/10/22(土) 22:27:56.31
>>670
くだらねーツッコミしてるお前よりかは、
建設的というか有益なんじゃね?
674 :名無しさん@お腹いっぱい。2011/10/24(月) 14:31:59.41
findコマンドでカレントディレクトリからファイルを探す場合、
find . -name '*.html'
としますが、これだと
./views/foo.html
のように、頭に「./」がついてしまいます。
今はsedを使ってこれを取り除いているのですが、find自体でこれをつけないようにすることはできませんか。

675 :名無しさん@お腹いっぱい。2011/10/24(月) 14:48:52.05
>>674
GNU findで、 -printf %P
677 :名無しさん@お腹いっぱい。2011/10/24(月) 15:18:00.71
>>675
うう、Macだからgnu findではなかった。。。
linuxだったらいけるんでしょうね。残念!
676 :名無しさん@お腹いっぱい。2011/10/24(月) 14:55:30.34
find * -name '*.html' で行けるかなと思ったけど、ドットで始まるディレクトリ
が検索対象にならないからダメでした…
678 :名無しさん@お腹いっぱい。2011/10/24(月) 18:16:30.00
前の担当者(フランスに渡米中)が書いたシェルに、
↓みたいなのがあるんだ。

exec 3<&0
exec < ファイル

while read line; do
ほげほげ;
done

exec 0<&3


これ、何でわざわざ execとか使ってるの? なんか意味あるの?
while … done < ファイル
って書けばいいんじゃないの?
担当者が書き方知らなかったんでしょうか?
680 :名無しさん@お腹いっぱい。2011/10/24(月) 19:59:38.22
>>678
http://www.faqs.org/faqs/unix-faq/faq/part3/section-8.html

POSIXではwhileリダイレクトはカレントシェルで実行されることになっているけど
伝統的なbourne shellではwhileリダイレクトはサブシェルで実行された
その問題への対処として、まさにそれと同じようなexecトリックが
上のページで説明されているよ
681 :名無しさん@お腹いっぱい。2011/10/24(月) 20:23:12.58
>>680
そんな深い意味があったのですね。ありがとうございました。
あやうくシェルを書き直すところでした。
686 :名無しさん@お腹いっぱい。2011/10/25(火) 22:59:20.26
>>681
その手があったか...!
679 :名無しさん@お腹いっぱい。2011/10/24(月) 19:23:26.39
使ってみたかったんじゃない。「exec使ってる俺ってステキ!」みたいな
683 :名無しさん@お腹いっぱい。2011/10/25(火) 18:07:14.98
シェルってゆーな
フランスに渡米中するな
685 :名無しさん@お腹いっぱい。2011/10/25(火) 19:06:53.52
>>683
そこツッコんだら負け。
684 :名無しさん@お腹いっぱい。2011/10/25(火) 18:34:31.52
シェル自体を書き直すのは尊敬するなあ
普通はシェルスクリプトの修正で済ませるだろうに

ぐらいにしとき
687 :名無しさん@お腹いっぱい。2011/10/27(木) 01:51:27.89
この中に何問くらい
学校のレポート課題があるんだろう…
689 :名無しさん@お腹いっぱい。2011/10/27(木) 08:51:53.40
>>687
そんなことがお前の心配事か?
691 :名無しさん@お腹いっぱい。2011/10/27(木) 13:25:53.60
128bit の数値って、シェルでそのまま扱えたでしょうか?

expr だと 32bit まででした…IPv4ならともかく、IPv6が…
692 :名無しさん@お腹いっぱい。2011/10/27(木) 13:31:07.16
今のバージョンの GNU expr は 128bitでも行ける。
693 :名無しさん@お腹いっぱい。2011/10/27(木) 13:31:28.94
bcでも使えばいんじゃないの。
695 :名無しさん@お腹いっぱい。2011/10/27(木) 13:42:20.00
>>692
う〜ん、GNU…最新版に更新させてくれるかなぁ…
できなきゃ、やっぱり桁毎にわけて管理するトリッキーな方法を採るしかなさげ…

>>693
あ、bc だと 64bit までいけましたが、128bitになると途端に挙動がおかしくなってくれまして。
697 :名無しさん@お腹いっぱい。2011/10/27(木) 13:57:31.01
>>695
じゃあdc
699 :名無しさん@お腹いっぱい。2011/10/27(木) 14:17:07.85
>>697
dc は対話モードだけかなぁなんて思ってたので、挫折してました…。
128bit が扱えるなら、もうちょっと頑張ってみます。
694 :名無しさん@お腹いっぱい。2011/10/27(木) 13:33:54.24
ldd expr したら、
libgmp とリンクしてるじゃん。
こりゃ、128bitどころか、10進で1万桁とか100万桁とかでも行けるわ。
696 :名無しさん@お腹いっぱい。2011/10/27(木) 13:51:09.95
libgmpってお絵書きソフトのライブラリだっ毛?
それがbit数とどういうご関係で??
700 :名無しさん@お腹いっぱい。2011/10/27(木) 16:36:58.12
IPv6アドレスの処理ならビット演算くらいしかしないでしょ。
16bitに分けて計算すれば?
それとも足し算して桁上がりとかあるのかい?

v6なら16bitバウンダリ以外で区切る状況は少ないでしょ。

マイクロソフト ワイヤレス ブルートラック マウス Arc Touch Mouse RVF-00006
マイクロソフト ワイヤレス ブルートラック マウス Arc Touch Mouse RVF-00006