1 :
名無しさん@お腹いっぱい。 :
2008/10/16(木) 00:48:38 シェルスクリプトの総合スレです。
スクリプトのお勉強・自慢・腕試しなどにどうぞ。
まずは注意点、リンク、地鎮祭など(
>>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 でトレースしましょう。
前スレ
シェルスクリプト総合 その12
http://pc11.2ch.net/test/read.cgi/unix/1218277263/
純正シェルが2ゲット
□人間初心者へのお願い: ・このスレはシェルスクリプトについてのスレです。 シェルの対話的な利用についての話やスクリプトと関係ないコマンドの 使い方の質問などはスレ違いなので無用に願います。 □シェルスクリプトでよく使うコマンド: 制御・条件判定系: [,test,expr,true,false,yes,getopts テキスト処理系: cat,awk,sed,tr,sort,uniq,grep,wc,head,tail,cut,paste,comm,join ファイル検索系: find,xargs (スペースなどを含むファイル名を正しく処理するため、 findは -print0、xargsは -0オプションを常に付けることを推奨 ただし、Solarisでは未対応。どうするんだろ?) ディレクトリ系: basename,dirname 出力系: echo,printf 対話コマンド制御系: expect http/ftpの処理自動化: wget,curl
v7うんぬんはどうなったんだ?
ファイル検索系: find,xargs (スペースなどを含むファイル名を正しく処理するため、 findは -exec command {} + を推奨。 他に -print0、xargsは -0オプションという方法もあるがSolaris非対応)
偏屈じじいの繰り言 総合 その13 に改名したらどうだ。スレタイ。
echo $'\344\271\231'
Solarisなんて使わないからどうでもいい
solarisでないunixとは?
grep の戻り値で疑問なんすけど grep -v でも引数の文字列が存在すれば0、存在しなければ1に見えます。 でも ps -ef | grep hoge | grep -v grep のときプロセスhogeが存在すれば、0存在しなければ1を返すのはなぜでしょう? そのリターンを返してるはずの最後の grep -v grep ではは毎回 文字列"grep"がひっかかってると思うんですけど・・・
$ echo grep | grep -v grep; echo $? 1 # grep以外の行はないよ $ (echo grep; echo foo) | grep -v grep; echo $? foo 0 # grep以外の行があったよ 要するに-vの時に「ヒットする」のは"grep"にマッチ「しない」行。
psの結果をgrepするのはお勧めしない。 関係ない文字列にマッチする可能性とかがあるから。 pgrep使え。
質問は-vオプション指定時の終了ステータスに関するものだから。
>>19 の頭に「grep の戻り値で疑問なんすけど」と書いてある。
>>21 は知識をひけらかしたくてしょうがない中二病。
>>24 それは手段であって、目的ではないことはエスパーすればわかる。
前スレで、command1 | command2 とやった時、
command2の終了ステータスのみが反映されますよね? と聞いてた人と
同一人物だということも、エスパーすればわかる。
エスパーは隔離スレに引っ込んでいなさい。
psに限らず、human readableを意図したコマンドの出力をgrepするのって間抜けだよなぁ。 ls -l とかもね。
人が見るためにgrepするのは問題ない。むしろ普通。
$?を得るのが目的なら、人が見るためじゃないしなぁ
psは出力書式が指定できるから、 どっちかというと扱いやすい方。
ps -ef | grep [h]oge
>>33 アフォか。vi hogeとかに引っかかる。
まあそうだけど。 pgrepが無い環境は私の周りにはほとんど無いから、pgrep使ってるよ。
sed についてですが、/を含むファイルを d で削除する場合、 デリミタを : に変更して対処する方法がありますでしょうか。 sed ':/usr/local/hoge:d' hoge.txt のように処理したいのですが、 デリミタの変更は s や y の無い構文では変更できなくて苦悩中です。 sed 's:dummy:dummy:; :/home/hoge.txt:d' hoge とやれば処理可能です。 やりたい事は、sed 's:/usr/local/hoge::' で文字列を削除しても 改行が残ってしまうので、改行まで削除したいと思っています。 何か良案ありませんでしょうか。
GNU sed なら man に書いてある。 他なら知らん。
sed -e '\:/usr/local/hoge:d' POSIXにもある
findでファイルリスト取りたいんですが ファイルタイプ dとかfとかlとか出せないですかね?
なんだって?
find -type d -exec echo d {} \; -or \ -type f -exec echo f {} \; -or \ (省略) っていう糞みたいな案が思いついた
43 :
名無しさん@お腹いっぱい。 :2008/10/20(月) 21:52:40
findのprintfで 名前,ユーザ,タイムスタンプ,権限,リンクならリンク先,ディレクトリとかファイルとかリンクとかの種類 みたいな感じのCSVを出力したいわけですよ しかしファイルタイプの取り方が分からず あとリンク切れだったら教えて欲しいですね
>>40 GNU findなら、
find /dir -printf '%y %f?n'
>>38 man に記載がありましたか。失礼しました...
>>39 ありがとうございます。
試してみます。
_, / ̄⌒i⌒ ̄\___ / /.; ; . | .; ヘ ;`i / .; ,; . .; | .; .; .; i ヽ._/ . .; .; .; | .; ヾ_/ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ i´ . ; | .; .; `i | `x ,. _ヽ | /----x'=-+ | 純正 find でヨロ | 6〉,/ 。i._|_|/。 `ヽ,| #l) | └-ヽ;ー‐'__└---===-┘ < c==<< ̄ ̄ ̄ ̄>>.===o゛ \_________ / ヾ二二//ゝ、 ___, ----―  ̄i⌒/´ ヾ  ̄ ̄/ `i⌒ヽー、 ̄ ̄| | | ヽ ゝー─---、_/---─ノ ノ | | | _ -‐
-exec ls -dF {} \; あたりで、出力をsedかawkで加工。
>>43 みたいな要求なら
-exec ls -dl {} \; -exec ls -dlL {} \; して、
比較とか含めてawkあたりで加工するしかなさそうね
perl(python, ruby)を避ける理由はない。
ありがとうございます。
今は手元のLinuxのGNU findでしか試せてないんですが、
>>44 の%yでf,d,lとかが取れるのはありがたいですね
実際に動かしたいのはsolaris(詳細は忘れた)も混ざってるので、使えないのかもしれませんが。
使えなかったら
>>42 >>47 >>48 を参考に-exec ls加工でやりたいと思います。
ちなみにリンク切れというのはGNU findでも検知できないんでしょうか?
日本語化されてるんだからマニュアル読みなよw あと「検知」した後どうしたいのか書いた方がいい。
sortコマンドでドメイン名を整列したいのですが、 bbb.example.com aaa.example.com example.com example.co.jp ↓ example.com aaa.example.com bbb.example.com example.co.jp のようなことは出来ますか? ピリオドを区切り文字にして、右側のフィールドから順に評価してくれればイイのですが。
>>52 awk -F. '{ for (i=NF; i>0 ; i--) { printf("%s ", $i) }; print("") }' | sort | awk '{ for (i=NF; i>0 ; i--) { printf("%s.", $i) }; print("") }' | sed 's/\.$//'
sort -i にした方がたぶん目的にはかなってるとおも
rev | sort | rev
58 :
52 :2008/10/22(水) 11:13:00
みなさま、どうも有り難うございます。
sortコマンドだけでは無理っぽいので、
>>55 さんの方法でやることにします。
"sort --sort=domainname"とか出来ればイイのですが。
>>56 > sort -i にした方がたぶん目的にはかなってるとおも
???GNUのsortだと -i は印刷不可能な文字を無視するだけのようです。
すまぬ、-f だ
60 :
55 :2008/10/23(木) 12:03:26
>>58 > "sort --sort=domainname"とか出来ればイイのですが。
コマンドを組み合わせてやっつけるのがシェルスクリプトの妙味ですので。
特殊な処理をコマンドに埋め込み始めるときりがないので。
なんでもかんでも無理にシェルでやろうとせずに、awkとかperlとかrubyとか使えば簡単なのに。
>>52 をsh抜いてawk, perl, ruby, pythonだけで書くと
>>55 より簡潔に書ける?
sortの行指向をうまく利用しているからかなり簡潔になってるよ。
#!/usr/bin/python import sys def sort_key(line): L = line.split('.') L.reverse() return L for line in sorted(sys.stdin, key=sort_key): sys.stdout.write(line)
puts ARGF.readlines.sort_by {|x| x.split(".").reverse}
だからcase insensitiveでソートしろと。
>>65 > L = line.split('.')
< L = line.lower().split('.')
>>66 > 〜 x.split(〜
< 〜 x.downcase.split(〜
以上スレ違い話終了
sort -n に対応する事をスクリプト言語でする時はどうするんかいな
system()
>>70 比較時に数値化(rubyなら to_iとか)
%w|hoge100fuga hoge9fuga|.sort_by {|e| [e.gsub(/\d+/, '#'), e.scan(/\d+/).map {|e| e.to_i}] } メンドクサ
map {|e| e.to_i}は map(&:to_i) と書けるが、そのくらいかな、縮むのは。
def embedded_numbers(s): pieces = re.split(r'(\d+)', s) pieces[1::2] = map(int, pieces[1::2]) return pieces ary.sort(key=embedded_numbers)
76 :
名無しさん@お腹いっぱい。 :2008/10/25(土) 21:56:24
ある文字列を,最後の1文字と,残りの前半部分の文字列に分けるにはどうすればいいですか? 最後の文字を変数 LAST_LETTER に,残りの文字列を FIRST_LETTERS に代入するように してもらえるとありがたいです。
s="foobarbaz" expr "$s" : "\(.*\)." expr "$s" : ".*\(.\)"
>>76 方法は2つ
1。正規表現
2。文字列の長さを測って、1引いた長さと、その場所から1文字をとる
>>77 惜しいね。そこまでわかってても、最後に LAST_LETTER FIRST_LETTERS に
代入するのができてないから、満点あげられないね。
>>78 77に具体的な答が(不完全だけど)出てるのに何言ってんだか。
具体的な答がないので点はあげられないね。
S="foobarbaz" FIRST_LETTERS=${S:0:${#S}-1} LAST_LETTER=${S:${#S}-1}
STRING=abcde FIRST_LETTERS=${STRING%?} LAST_LETTER=${STRING#"$FIRST_LETTERS"} echo "$FIRST_LETTERS" echo "$LAST_LETTER"
>>78 >>82 は、正規表現も使っていないし、文字列の長さも測っていない。
よって、方法は3つ(以上)あることになる。
スレ違いだがLEADING_LETTERSにしてくれ。
85 :
76 :2008/10/25(土) 23:44:06
回答ありがとうございました。
>>84 LEADING_LETTERSの方が良かったですかね。
指摘ありがとうございます。
>>81 正直、ここらの文字列操作はどれがbash拡張なのかどうか、
/bin/shがbashな環境にいると判別できないな。
>>86 UNIXで/bin/shがbashな環境なんてあるの?
あ、opensolarisとか??
>>88 LinuxはUNIXじゃないという煽りなんですね お疲れ様です
>>90 LinuxをUNIXにしたらLinuxが嫌なんじゃない?
UNIXじゃ無いのがアレの誇りなんじゃないの?
>>90 linuxというくくりでは/bin/shが何なのかは明確じゃないからな。
Mac OS X はスレ違いだろ
>>93 なぜ?
LinuxやFreeBSDと違って、れっきとしたUNIXだよ。
アスファルトみたいな燃料じゃちょろちょろとも引火しないぜ
前スレか前々スレあたりで、"$@" と書くべきか、${1+"$@"}と書くべきかって議論、 あったと思うけど、 zshで、setopt shwordsplit してる環境だと、 ${1+"$@"} ではスペースが不本意に解釈されてしまって、引数がそのまま引き継げない。 やはり、単純明快に "$@" と書いた方が良いという結論。 $ zsh zsh$ setopt shwordsplit zsh$ set 'hoge boke' zsh$ for i in ${1+"$@"}; do echo "$i"; done hoge ← 2つに分かれてしまう boke ← 2つに分かれてしまう zsh$ for i in "$@"; do echo "$i"; done hoge boke ← 正常
>>96 > zshで、setopt shwordsplit してる環境だと、
当たり前やんw
すげえピンぼけ
>>97 なんで当たり前?
zsh以外では setopt shwordsplit状態がデフォだよ。
それで、${1+"$@"} は "$@"と同様に動作する。
で、${1+"$@"} が、word split されるのは zshのバグと言える。
findでファイル名に数字がつかわれてないものを引っ掛けたいんですが -name のかっこいい正規表現でいけないですか?
>>99 findの -name は正規表現ではありません。はい次
パス付きじゃなくてファイル名に対してはできないですか?
>>103 -regex を使うなら、フルパスでしか指定できない。そういう仕様。
>>99 -regex '.*/[^/0-9]*$'
了解です
というか
>>102 でファイル名だけになってますね
ありがとうございました
>>96 試したみたがそうはならんな。
まあzshスレの話題のような気もするが。
ちなみにv7 shもheirloom sh(OpenSolaris)も${1+"$@"}と書く必要がある。
(だから必ずそう書けといっているわけではない; 知っておいた方がいいというだけ)
>>107 zshのバージョンは? 4.x または 5.x で症状が出る。
あと、ちゃんと setopt shwordsplit を設定したか?
$ cat /tmp/foo ←
>>96 のコピペ
setopt shwordsplit
set 'hoge boke'
for i in ${1+"$@"}; do echo "$i"; done
for i in "$@"; do echo "$i"; done
$ zsh /tmp/foo
hoge boke
hoge boke
$ zsh --version
zsh 4.3.4 (i686-pc-linux-gnu)
zsh-newuser-installをquitしたので設定は何もない。
>>109 zsh 4.2 だと
>>96 の指摘通りになる。
zsh 4.3 だとバグフィックスされた?
111 :
109 :2008/10/27(月) 11:55:03
setopt shwordsplitしようがしまいが結果は変わらんな set 'hoge baka' ahoでも。
>>111 だから、zsh-4.2 で試せと。
zsh-4.2 ならまだそう古いバージョンじゃないし、まだ使われてるし、
汎用性考えると "$@" と書くべきだな。
初心者です。 ファイル名が、 年月日.種類.年日.場所.更新日時.拡張子 となっているファイルを扱っています。 年月日および年日(対応してます)は全部でおよそ400、場所は200〜300あり、 5種類分あるので、各種類約10万ファイル、全部で50万ファイルくらいあります。 この中から、年月日.種類.年日.場所.*.拡張子だけ同じで、 更新日時が違う複数のファイルを見つけ出し、古いファイルを消さねばなりません。 例を示すと ./2001.08.29/MOD15A2.A2001241.h15v03.005.2007052031007.hdf ./2001.09.06/MOD15A2.A2001249.h15v03.005.2007054111501.hdf ./2001.09.06/MOD15A2.A2001249.h15v03.005.2008278130254.hdf ./2001.09.14/MOD15A2.A2001257.h15v03.005.2007056161438.hdf こんな感じです。この場合、2番目のファイルだけを消したいです。 ファイル名が完全一致の重複ではないだけに、どうしていいかわかりません。 できればお教えください。 ちなみにディレクトリ構造は、種類-年月日-ファイル、となっています。
そのくらいの量だとシェルには荷が重くないか? Perlあたりで書いた方がよくない?
>>113 ヒントだけ。
全ファイルのリストをファイルに落す。(1行1ファイル名)
(ファイル作りたくなければパイプでも桶)
そのファイル(パイプ)を入力として、
対象フィールド限定で(更新日時フィールド以外で) uniq -d で重複行を出す。
その重複行それぞれについて、更新日時フィールドをワイルドカードにして
ファイル名リストをとる。この時、更新日時フィールドは結局辞書順に
並んでいるから、最後の行以外のファイルは古いファイルと判定できるから、
最後の行以外のファイルを rmする。
以上を、uniq -dが出力した各行について行なう。
>>115 ありがとうございます!
考えてやってみます。
シンボリックリンクの値を読む方法はreadlink以外にありますか? readlink(1)がSUSv3に見当たらなくて驚いています
ls -l
>>113 ファイル名の桁が揃っていると仮定する。
sort -r d.txt | awk '{ k=substr($0, 0, 40); ++a[k]; print a[k], $0; }' | awk '$1 != 1 { print $2; }'
>>117 perl -le 'print readlink($ARGV[0])' /hoge/file
シェルスクリプトを実行するのに sh hoge.sh と打ち込んでいるのですが、これを hoge.sh と、ファイル名だけで実行できるようにするにはどうすればよいでしょうか?
PATH
chmod
シェバン
さて、誰が本物のエスパーか
>>121 install -m 755 hoge.sh /bin
127 :
名無しさん@お腹いっぱい。 :2008/11/02(日) 20:00:54
あるフォルダ内にファイルが存在する場合、 フォルダ内のファイルを移動させたいのですが、 どういう条件式で記述するのが良いでしょうか?
>>127 UNIXでフォルダと言えば、MHのフォルダのことだよな。
フォルダ内の全ファイルを移動するには、
refile all +newfolder
130 :
名無しさん@お腹いっぱい。 :2008/11/02(日) 20:20:30
>>129 MHフォルダ?分かりません。。。
現在だと
if[-d hoge] ; then
rm *** ***
fi
としてますが、エラーとなります。
何がまずいでしょうか?
133 :
名無しさん@お腹いっぱい。 :2008/11/02(日) 20:31:15
>>131 マジですか。。。
初心者をいじめないで下さい。
てかPATHもchmodもわかんないでシェルいじるのは危険すぎねえ?
>>130 とりあえず、エラーの原因は ifの後ろとか、[の後ろとか、]の前に
スペースを入れていないため。
ところで、ディレクトリが空じゃなかったら、
ファイルを移動したいのか?削除したいのか?
>>130 と
>>127 で言ってることが矛盾してるのだが、、
136 :
名無しさん@お腹いっぱい。 :2008/11/02(日) 21:52:13
>>135 すみません、それではもう一度質問です。
フォルダ内のファイルが存在すれば
そのフォルダ内のファイルを他フォルダへ移動する(mv)という処理を
スクリプトで書くとどのような記述が良いでしょうか?
>>136 多くの場合、
mv /hoge/* /hage 2> /dev/null
だけで十分なことが多い。
ファイルがなければ何も起きないし、そのエラーメッセージは捨ててるから。
ドットファイルにこだわるなら、
mv /hoge/* /hoge/.[^.]* /hoge/..?* /hage 2> /dev/null
かな。
138 :
名無しさん@お腹いっぱい。 :2008/11/02(日) 22:12:06
>>137 ありがとうございます、
確認してみます。。。
139 :
名無しさん@お腹いっぱい。 :2008/11/02(日) 22:24:00
できました! ありがとうございました。 以前会社でやると エラーがでましたが、 フォルダ内にファイルがなかったときは mvコマンドでエラーにならないのですか?
これが世に言う通常エラー出力のリダイヤルですか?
二度出力してどうする
142 :
121 :2008/11/03(月) 01:17:24
>>122 ありがとうございました。パス通すだけでよかったんですね、下記で動きました。
$ PATH=$PATH:/home/user_name
$ export PATH
>>123 パーミッションは大丈夫でした
>>124 それも大丈夫でした
>>126 ちょっとやりたいこととは違いました。
>>128 は私ではないです。
問題の無いエラーなら無視するw
大事なことなので二度出力しました
関数を子シェルでも使えるように宣言できますか
できません
環境変数を子シェルに引き継がせない方法ありますか
env -i
149 :
名無しさん@お腹いっぱい。 :2008/11/06(木) 22:00:56
vi
たしかに↓でPCが逝ってしまいますね.rm -rf / よりはマシかもしれんが :(){ :|:& };:
>>150 やってみましたが、何も起きませんが、、
$ :(){ :|:& };:
: is a special built-in
あと、念のため、
$ ksh
$ :(){ :|:& };:
ksh: :: illegal function name
唐突に「たしかに〜」って、なんだよ。
bash じゃないと無理なのねorz :() defines a function named : with no arguments. { :|:& } is what the function does. :|: calls itself twice (with a pipe between the two), and the & at the end runs it in the background as a new process. The ; finishes off that command, then the last : runs the function, starting the fork bomb (as each run starts 2 new processes, each of which starts 2 new processes...).
どっかのMLあたりのネタ?
すげー試してぇ
>>153 bashでも何も起きなかったぞ。
bash$ :(){ :|:& };:
bash: `:': not a valid identifier
fork爆弾だろ
シェル関数名に:を使って字面の面白さを狙ったものと思われるが、 高度なAAを見慣れたネラーには面白くもなんともない。
2行目、AAとしてしか見れない人も可哀想だな
いたずらコードを仕掛ける場合でも、 純正シェル対応にしておかないと効果半減する ということですね、わかります
大吟醸じゃダメですか。
cygwinで(bashで)試してみたら、本当にPCが使えなくなったw みんなはイタズラしないようにな
ulimit -u 10 してからやれよ。
オプションを処理したあと、引数が残っていたらファイルとして、 そうでなければ標準入力を処理したいのですが、 if [ $# -gt 0 ]; then fuga "$@" | hoge else fuga | hoge fi みたいにやらずにスマートにするにはどう書いたらよいのでしょうか。 上の例のfuga自体は引数のファイルも標準入力もOKとします。
>>164 そのまま、
fuga "$@"
だけでOK。
$# が 0 なら、"$@" は消えてなくなってくれる。
( ${1+"$@"} と書く流儀もあるが、
>>96 の指摘の通り zshにバグがあるので、
"$@" の方がお勧め)
> zshにバグがあるので 古いのだけだろ。
>>166 純正シェルスクリプトは古いシェルをも想定しなければならない。
しかも、zshの件はそんなに古くないバージョンの話だし。
バグ持ちにあわせる必要はない。
動いてなんぼ。原因がバグであろうと、普及していればそれが仕様。 存在するものに合わせなければならないのは当然。
これからバグだらけのシェル開発するよ
バグのない純米シェルはありませんか?
純正シェルスクリプトなら zsh で動かすことを考慮する必要ないのでは
/bin/sh -> zsh と symlinkされたOSがあったりする。
zshみたいなうんこシェルとそれが/bin/shになったOSよりSolaris優先。
bashよりはマシだろ スクリプトの速度的に
Solarisもbashになったけどな。
それほど大掛かりなことをする訳ではなく、 シェルスクリプトから軽くXML内の値を参照したり、 書き換えたりしたいんだが… XMLStarletなるツールを使えば、ほぼ満足の行く内容で目的は 達せられるんだけど、なんかもっとメジャーな、デファクト スタンダードなツールってありますかね? なんか、検索しても、イマイチ普及しているように感じられないん ですけど。
${1+"$@"}みたいにする意味をネットで調べたくても、 うまく検索できないんだよなぁ。 シェルスクリプト本でも読みに本屋行ったほうが早いかも。
>>178 xmlgawkてのはどう?
デファクトじゃあないだろうけど
>>179 $1が定義されてたら"$@"で置換。
純正シェルは$1が未定義の時に"$@"が空文字列に置換される。
意味を知りたいんじゃなくて 意味の知り方を知りたいだろう。
いや、意味というか仕組みを知りたくて、 そのために調べようとしても分からなかったので、 知り方も知りたかったです。(で、分からなくてボヤいた。) で、Parameter Expansionを利用した細工とも違うみたいで、 やはり仕組みはよく分からなかったです。 # ${parameter:+word} はmanにあるけど、 # 今回の場合 ":" は無いので。
: がない場合の動作もmanに明記してあるよ。 (FreeBSDのshとbashで確認)
見当たらん・・・
:+ とか :- とかの書式について書いてある近辺に、 : の有無で動作がどう変わるか書いてある。 ${parameter+word} 自体で独立した項目にはなってるわけではない。
あぁ、「colon」か。「:」で探してた。 ども。
>>181 嘘書くな。
純正シェルでも、$1がセットされていなくても、
"$@" は空文字列にはならない。(何もない状態になる)
よって、${1+"$@"} にする必要無し。
v7shなら"$@"は空文字列になる。 具体的なシェルを書かない純正論は空論。
${1+"$@"} にする(ことがあった)のは空文字列対策じゃないわけだが、、
以前くだ質で読んだ気が
v7$ cat foo c=0 for i in "$@"; do echo "$c: $i" c=`expr $c + 1` done v7$ ./foo "1 2 3" 4 5 0: 1 2 3 1: 4 2: 5 v7$ ./foo 0: v7$ cat bar c=0 for i in ${1+"$@"}; do echo "$c: $i" c=`expr $c + 1` done v7$ ./bar "1 2 3" 4 5 0: 1 2 3 1: 4 2: 5 v7$ ./bar v7$
そんなおおげさにしなくても、echo foo "$@" bar で確認できるでしょ。
196 :
名無しさん@お腹いっぱい。 :2008/11/13(木) 19:11:37
梶谷秀
バグがあっても周囲がそれに合わせるべきと見なされる存在、 それが純正シェル(笑)
誰もが通ったor通ってる道だ
いや、別にそんなに面白くはない。
誰もが通る道だが ネット検索や入門書などで調べる人 頭から調べようとしない人 検索しても目的のものを見つけられない人 いろいろだわな。
俺はそんな道は通ってないが、もちろんシェルスクリプトに関してはエキスパート。
203 :
名無しさん@お腹いっぱい。 :2008/11/14(金) 23:12:52
Xパート?
標準出力と標準エラーってなんで分かれてるんですか
シャバン
>>204 例えばトイレには男子トイレと女子トイレがある。
本質的にはそれと一緒。
大昔は、標準出力用のディスプレイと標準エラー用のディスプレイに分かれてた名残と聞いたような聞いてないような
>>204 $ foo file1 file2 file3 | wc
file2: not found
10 23 445
"file2: not found"までwcしても意味がない。
エラー情報だけ別に扱うことができる。
GNU系のコマンドがusageをstdoutに出すのが困る。
オプション間違ってた時に。
COMMAND.COMではstderrがリダイレクトできないので、usageをstderrに吐く ツールはリダイレクトしてチートシートを作れなくて面倒だったなぁ
そしてstderrを自由にリダイレクトできないcsh批判へ ↓
できればいいじゃん
csh ? なんですだそりゃ?
標準エラー入力を新設するべきだ。 hoge | less ってやった時、lessは標準入力からパイプを読むが、 この時、less自体の操作のためにキーボードを読む必要があるが、 /dev/ttyを直接読まずに、「標準エラー入力」を読んだ方が美しいし応用も効く。
キーボードを読む必要があるのなら、キーボードを読むべきじゃないの? もしかして、エラー出力≒コンソール出力、って思ってるなら、 あんまりそういうことはないとだけ言っておく
バックグラウンド起動したときに出るpidとかのメッセージは何出力ですか?
>>215 $ : & > /dev/null
とか
$ : & 2> /dev/null
とかやってみて確かめればいいだろ。
>>216 それだと : の stdout や stderr が /dev/null になるんじゃない?
exec 2>/dev/null
: &
とかしないと
>>216 [root@migii ~]# : & > /dev/null
[1] 2420
[root@migii ~]# : & 2> /dev/null
[2] 2421
[1] Done :
[root@migii ~]#
>>214 無端末状態で lessを起動しようとすると、not a tty って言って拒否されるけど、
標準エラー入力があれば、/dev/tty をじか読みしないから起動できると言う
メリットがある。
「キーボードを読む必要がある」のじゃなく、
「最終的にキーボードにつながっているはずのパイプとかソケットとか」
を読むための「標準エラー入力」
AEGISにはあったな。
>>214 は知ったかだな。
コンソールとTTYもまた別物だし。
何が、"言っておく" だ。
>>219 controlling terminalを知らない人?
>>222 もちろん知ってるよ。
知った上で言ってるよ。
制御端末はどちらかと言うとプロセス管理上の問題(シグナルとか)だから、
今の話とはちょっとずれてる。
制御端末がなくても標準エラー入力でlessは動作可能。
>>222 は、controlling terminal と pseudo terminal を混同してる悪寒。
pseudo terminalだったとしてもlessにとって必須というわけじゃないしなぁ。
パイプのような dumb入力でも動作可能。
どうでもいいが、仮名にしても標準エラー入力でなく もうちょっとマシな命名してくれよ。
標準エラー出力に対するものだから標準エラー入力と言ってるだけで、 今から命名するなら「標準診断入力/出力」とかだろな。
228 :
名無しさん@お腹いっぱい。 :2008/11/15(土) 18:24:10
ファイルのタイムスタンプを、引数指定の秒数(または分や時間)だけ 相対的に進める(または遅らせる)ようなシェルってどう書きますか? touchやlsを駆使すればできそうですが、なるべく奇麗な方法でよろしこ。
touch -A
>>228 GNU dateで、
touch --date=`date --date='1 year ago'` filename
>>231 それだと、「現在時刻」からの相対時刻になっちゃうじゃん
質問は元のファイルの時刻からの相対
>>233 シェル自体の標準エラー出力だよ。
だから、コマンド起動時に単純に 2> /dev/null とかでリダイレクトできないから
わかりにくいだけ。
補足すると、
>>217 の言うように、exec 2>/dev/null すれば確かめられる。
ただし、exec 2>/dev/null した瞬間からシェルのプロンプトも
表示されなくなるので、操作困難になる。
ついでに、シェルのプロンプトも標準エラー出力というわけだ。
236 :
名無しさん@お腹いっぱい。 :2008/11/15(土) 20:00:58
$ find . -maxdepth 1 -name '*foo*' | xargs mv dir/ のようにして '*foo*' にマッチしたファイルを dir/ 下に移動したいんですが、パイプ からの出力がdir/ の後ろに位置してしまい、 $ mv dir/ $files のように解釈されてしまう為、うまくいきません。 $ mv $files dir/ のように解釈させるにはどうすればいいですか?
-i {} dir
-exec涙目
xargsはobsolete -exec mv {} dir +
-exec sh -c 'mv "$@" OOO' dummy {} +
>>243 もし、& 付けた後の pid表示が邪魔だから消したいという話なら、
$ (command &) 2> /dev/null
で消せるよ。
実は、
$ (command &)
だけでも消えるんだけどね。
今使ってるシェルを知るには$SHELLを見ればいいって言われたんだけど bashからcshに変えても値が/bin/bashのままなんだけど・・
>>245 cshはバカだから$shell。
% set
% setenv
すれば、一覧が見れる。
249 :
名無しさん@お腹いっぱい。 :2008/11/16(日) 10:20:41
kshって色づけ出来ないの?
cshは、もはや継続行のコメントアウト部分のみしか羨ましくない
>>228 ,248
つ touch -d @`stat -c %Y hogehoge | xargs expr -3600 +` hogehoge
$ touch hogehoge
$ ls -l hogehoge
0 -rw-r--r-- 1 xxx users 0 Nov 16 22:05 hogehoge
$ sudo touch -d @`stat -c %Y hogehoge | xargs expr -3600 +` hogehoge
$ ls -l hogehoge
0 -rw-r--r-- 1 xxx users 0 Nov 16 21:05 hogehoge
ただしGNU coreutils使用。
>>251 GNUありでいいならもっと簡単にできるだろ。
うぉ -r ってのがあるのね・・・アリガトン>252
なぜsudo?
あれ、ホントだ。たぶんchownと脳と指が取り違えて打ってた。 この癖はリアルで危険だから直さんといかんな・・・
キ違いに刃物
258 :
名無しさん@お腹いっぱい。 :2008/11/17(月) 22:10:51
教えてください。 #!/bin/sh TestFunc() { echo $1 # ここでは ls -l "aaa bbb" $1 # ここでは ls -l aaa bbb と処理されてしまう } TestFunc "ls -l \"aaa bbb\"" Bシェルで関数に引数を与え、コマンドを実行することを 考えています。 コマンドの引数にスペースつきのものを含む場合、ダブルコーテーションで くくっていても、実行される場合は外されてしまうようです。 そもそもechoで出した場合は正しく表示されるのに、実行した場合 ダブルコーテーションが外れてしまう理由も良く分からないのですが、 どのようにすれば正しく実行できるのでしょうか? TestFuncc() { $1 $2 "$3" } TestFunc "ls" "-l" "aaa bbb" とすれば良いのは分かるのですが、コマンドの引数が変わった場合に対応できないので 汎用性が落ちますし、出来れば一つの文字列で関数に渡したいのです
>>258 TestFunc()
{
echo "$@"
"$@"
}
>>259 TestFunc()
{
echo "$@"
eval "$@"
}
だろ?
-a とか * とかよりも素人には消すのが難しいファイル名ってありますかね
ありがとうございます。
>>259 は既に試してみましたがダメでした。
>>260 は、今環境が無いので、明日会社で確認してみます。
この場合は$@なの? $*じゃだめなのkすら
>>264 文字化け系は、取り合えず消したくないファイルを
別のディレクトリに退避して、rm TAB{印字可能文字}*とかで、何とかなる。
・・なってほしい。
文字化け系のファイルがいっぱいあると、 消したくないファイルの特定すら面倒だし、間違う可能性もある。
*って消しにくいの? rm * でまっさきに消えるじゃん 普通の操作で消去できないファイルを作るのは ".[ファイル名]" にするのが常套手段 名前を厳密に指定しない限りrmでは消せないし
どこが常套手段なんだろう。意味不明。
第一消せるし。zshならGLOB_DOTS。 そんな挙動を前提にrm *とかやってると痛い目を見るぞ。
>>261 rm -i * とされると rm -- -a や rm \* や rm '*' なんて知らなくても、文字化け系でも大抵何とかなる
先に必要なファイルをあらかた退避したら、作業もそう面倒でもない
ちょっとした嫌がらせ?部下に勉強させたい?なら .* とか
^Ha (スペース+制御文字^H+a) として普通に ls だと a にしか見えない、rm a でも rm a* でも消えない、とかかな
zshでタブキーをぱかぱか押して補完させれば大体なんとかなる
>>262 >今環境が無いので、明日会社で確認してみます。
シェルの環境がないって? どんな環境?
まさか、自宅にはWinしかないとか?
そんな人に解答したくないね。
ここはみんな、UNIXからアクセスしている人のみのはず。
しょうもない妄想乙
>>271 そしてたまにzshが落ちる、と。
わかります。
>>272 お前は解答しなくていいよ。迷惑だから。
携帯電話でそんなのがあるらしいぞ
278 :
名無しさん@お腹いっぱい。 :2008/11/19(水) 07:03:16
ファイルの先頭行だけを表示しない方法ってありますか? -------------- $ cat hoge aaa bbb ccc -------------- こういうファイルがあるとして、先頭行だけを表示しないようにしたい。 awkを使って、以下のようにできるけど、もっとスマートにしたい。 $ cat hoge | awk '{if (NR > 1) print}' イメージ的にはこんな感じで。 $ cat hoge | cutline 2-
>>278 「もっとスマートにしたい」というなら、
まずは自分で書いてる無駄な cat が無駄であることに気づけw
>>279 に補足すると、tailの古いバージョンでは
tail +2 hoge
282 :
>>278 :2008/11/19(水) 08:18:35
>>278 awk使うにしても、if文が無駄だな。
awk 'NR > 1 {print}' hoge
285 :
名無しさん@お腹いっぱい。 :2008/11/27(木) 07:43:58
grepで質問です!! 以下のような制御(色)文字を含んだファイルがあるとします。("生データ"とよぶことにします) $ cat -t hoge.dat ^[[0;31mhello^[[0mend catコマンドで表示するとこんな感じになります。("表示データ"とよぶことにします) $ cat hoge.dat helloend で、"表示データ"をgrepするために以下のようにしたのですが、うまくひっかけることができません。 $ grep ^hello hoge.dat grepのaオプションも使ってみたのですが、だめでした。 表示データをgrepする方法で、いい方法を教えていただきたく。 よろしくお願いします。
>>285 stringsで抜き出したものをgrepするとか。
>>285 単に、grep hello する。(^なし)
あるいは、grep mhello
>>286 そういう問題じゃないだろ。[0;31m とかはテキストだから。
「行頭」とかをちゃんと区別したいなら、 エスケープシーケンス(^[からアルファベットまで)をちゃんと除く必要がある。 カーソル移動とかあれば、行頭って何って話になるけど。 sed 's/^[[^a-zA-Z]*[a-zA-Z]//' hoge.dat | grep ^hello ^[ は当然エスケープ文字な。
>>288 あほか。それだとエスケープシーケンス中の数字やセミコロンに対応してない。
仮に英文字だけのシーケンスだとしても、hello自体まで削除される。
いや、
>>288 で合ってる。
エスケープ自体をsedに入れるのに難があるけどな。
馬鹿をさらした
>>289 は何をどう読み違えたんだ?
あほか? エスケープシーケンスは端末依存なので、それを解釈する端末エミュレーションも実装しないとだめ。 まぁ、がんばってくれ。
>>292 あほか。
エスケープシーケンスは、
ESCで始まり、英文字以外が0文字以上続いた後、英文字1文字で終る、
ということは決まっている。
端末(TERM)が変わって、具体的なシーケンスが変わっても、
シーケンス自体の規則は変わらない。
だから、すべてのシーケンスを削除するのが目的なら、
>>288 でよい。
というか、
>>288 の sed に g 付けとけよな。凡ミス指摘な。
296 :
288 :2008/11/27(木) 09:55:51
なんかあほばか呼ばわりされて白熱してるとこすまんが、g 付け忘れた。 「行頭」だけなら最初のシーケンス消せばいいだけだからなくても動くけど。
>>293 hp端末の制御文字列はエスケープシーケンスと認めてもらえないんでしょうか。
>>298 カーソル移動のエスケープシーケンスも、
>>293 の言う範囲に含まれる。端末によらず。
>>299 あほ。カーソル移動して文字列を逆順に出力してたらどうやってgrepすんだよ。
ツマラナイカラヤメロ
>>302 知能の足りなさを認められない、あほ。惨め。
>>303 カーソル移動の件に関しては
>>288 が一番最初に断ってるのだが、読み落したかい?
さも、
>>300 で自分が最初に発見したみたいに書き込んでるけどさw
306 :
名無しさん@お腹いっぱい。 :2008/11/27(木) 17:53:24
tcl の文法が嫌いなので expect を使いたくないのですが、 その代用として、同様のツールがあれば教えてください。
pexpect
expect.rb
>>307 > pexpect
ありがとうございます! かなり良さ気ですね。
それに python は大好きなので、是非それを使ってみようかと思います。
>>306 zsh で zpty
使ったことないけど
今使ってるシェルを知るには echo $0 が一番らくだということに気づいた $SHELL だったり $shell だったり どっちも入ってなかったりするから
>>311 # echo $0
-su
これはなんのシェルですか?
>>311 $ cat hoge
#!/bin/sh
echo $0
$ ./hoge
./hoge
結論: $0 でシェルはわからない
>>315 後だしとか言われても。。。
スレの前のほうでやってた流れから、
多分そういう事じゃないのかと思っただけで。
で、
>>312 については多分そういう前提の上でうまくいかない例を挙げてるわけで。
そもそも俺は
>>311 とかでもないから、見苦しいとか言われてモナー
>>313 のような「当たり前」の事をわざわざ発言する必要はないのだから、
>>311 はインタラクティブ環境の事を言ってるのだろうと推して知るべし。
>>311 $ ln -s /bin/sh hoge
$ ./hoge
$ echo $0
./hoge
インタラクティブ(笑)だぞ
なんか、無い知恵振り絞って必死だね。内定取り消されたの?
>>314 $0に何がセットされるかは、
インタラクティブ環境かどうかとは直接は関係ないという点は理解してますか?
>>319 何の脈絡もなしに、突然新しい話題(内定取り消し)が出てくる時は、
心理学的に、本人自身がその話題(内定取り消し)で悩んでいる場合が多い。
319 自身とか、319の息子とかね。
ということにしたいのですね。
なんだこの流れ シェルスクリプトのスレだろ?
他に方法あるの?
スクリプトスレでインタラクティブの話題? インタラクティブなら ps 結果を grep $$ するのも1つの方法 になりえるかなぁとも思ったけど上手くいかない状況もあるかも あとウチの環境では少なくとも csh の場合はインタラクティブで echo $0 はエラーになる > 他に方法あるの? 他にとかいう以前に、echo $0 含めそもそも汎用的な方法なんてないんじゃなかろうか?
>>325 psの結果を grep $$ するくらいなら
ps -p $$
>>317 インタラクティブ環境の話題はスレ違いだから、
インタラクティブ環境の事は言っていないのだろうと推して知るべし。
ぷぷぷ。必死だね。
もし、そうなら。
>>313 のような「あたりまえ」の知識を披露せずに、
「スレ違い」と切って捨てればよい。
>>327 本当は
>>313 が指摘するまで知らなかったんだろ?
後からなら「あたりまえの知識」ということにしてごまかせるわな。
あと、回答者にとって「あたりまえの知識」なのは当たり前。
それを知らない質問者が質問してくるから
あたりまえの知識を回答するのがあたりまえ。
このスレはもっと紳士的なシェルスクリプターの集まりだと思っていたのだが…
必死すぎ。www
そう仮定するなら、
>>311 は明らかに間違っているわけだが。これをどう説明するのだ? www
実行すらせずに思いつきで書いたとでも? www
お前らシェルスクリプトの事話せよw
>>331 俺は汎用性よりも可読性重視だから仕事では自分で一から作るモノは/bin/bashだな。
上の方にでてた四則演算はexprじゃなくてletとか使う。
すんません。今までシェルスクリプト触ったこと無いものなのですが 突然、SCPとftpでファイル転送するの作ってといわれて途方にくれています。 まずシェルスクリプトのことを学ぶのにどこを見ればいいのか また上記のことを行うのに参考になるサイトなどありましたらお教えください。 お願いします
一般的なプログラミングの経験にもよるけど、 今後も書く可能性があるのなら、 本買ってひととおり読んだ方が早いよ。
>>337-338 ありがとうございます。
C/C++を大学でやってきた程度で
鯖をFedoraやDebianで本読みながら立てたくらいです。
Shがどんなものか、触りをWEBで確認したくらいで
サンプルコードを色々弄くってみた程度で、まだ全く使い方がわかっていません
SCPでファイル取得して、FTPで他の鯖に転送という、よくわからない要求です
もう少し勉強します。。。
>>330 は言ってることがつながってないので、
何を主張したいのかわからん。
主張のないものに「反論がない」と言われても、それで
>>330 の勝ちにはならない。
>>320 も書いてるが、
$0に何がセットされるかは、インタラクティブ環境かどうかとは直接関係ない。
それを「インタラクティブだから$0にシェルがセットされる」と主張されても
当然間違い。
$SHELLについては、普通にloginすればログイン時にセットされるが、
その後、値を書き換えたり unsetすることもできる。
値を書き換えたり unsetした状態でシェルを起動しても、
$SHELLは改めてはセットされない。
よって、$SHELLではシェルを判定できない。
$shellについてはcsh系の方言だから、B-sh系でセットされていない。
もうやめなよ
>>339 ftp, FTP, SCP, Sh
これらの大文字・小文字の区別はいったいなんなんでしょうね。
きもちわるい。
>>340 loginがシェルのargv[0]に渡すものは決まっている。
treeコマンドで、以下の様にディレクトリやファイルの詳細情報も 合わせて表示させるにはどうすればよいのでしょうか? # tree /home /home `-- TEST drwxr-xr-x 3 root root 4096 2008-10-26 22:28 |-- AA drwxr-xr-x 3 root root 4096 2008-10-26 22:28 | |-- test.csh -rwxr-xr-x 1 root root 4836 2008-11-30 18:25 | |-- test.csh.org -rwxr-xr-x 1 root root 3416 2008-11-29 23:10 | `-- hoge.sh -rwxr-xr-x 1 root root 1834 2008-11-29 23:24 |
>>344 それは「シェルスクリプト」スレに相応しい話題ですか?
>>343 login経由でログインするとは限らない。
>>344 シェルスクリプトと関係無いから次からはくだ質行ってくれ。
各コマンドの事なら大抵はmanかhelpよめばわかるはず。
# tree --help
usage: tree [-adfgilnpqrstuxACDFNS] [-H baseHREF] [-T title ] [-L level [-R]]
[-P pattern] [-I pattern] [-o filename] [--version] [--help] [--inodes]
[--device] [--noreport] [--nolinks] [--dirsfirst] [--charset charset]
[<directory list>]
(snip)
-p Print the protections for each file.
-u Displays file owner or UID number.
-g Displays file group owner or GID number.
-s Print the size in bytes of each file.
-D Print the date of last modification.
>>343 loginは argv[0]の頭に - を付けるが、
環境によっては、頭に - を追加するんじゃなくて、
頭の 1文字を - に置き換える。
だから、(イマドキいないと思うが)cshユーザーの場合、
cshの頭の1文字が - に置き換わって -sh になる。
よって、$0 を見て判別するのも無理がある。
>>349 >>346 については、xdmなんかでログインすれば loginは経由しないし、
telnetとかsshの場合もloginは(今は)呼んでいない(自前処理)のはず。
そうじゃなくても、X上でxtermとか開いてもloginは通らないしね。
>>350-351 「あきらかにするように」とか「脳内環境」とか言ってる奴(
>>349 )に
詳しく教えてやることないよ。
「教えてください」って礼儀正しく言う者にだけ教えればいい。
353 :
名無しさん@お腹いっぱい。 :2008/12/01(月) 08:56:28
このスレを見てるだけの傍観者ですが教えてください
>>351 > telnetとかsshの場合もloginは(今は)呼んでいない(自前処理)のはず。
嘘つき。telnetは呼んでる。
RFC1416 の Authentication option を使えば呼ばれないはず。 サポートしてない/サポートしてるけどデフォルトでは使わない実装が多いようだけど。
今やPAM(OSF RFC 86)化されてるのが多いしなあ。
何と戦ってんだかわけわからなくなってるなw 結局こんな感じだろ? echo $SHELL これはsh系以外アウト、つまりまったく実用的でない ps -p $$ 理屈的にまわりくどい echo $0 理屈的にも納得かつほぼ問題なし
361 :
:2008/12/02(火) 04:02:11
echo $0 can't read "0": no such variable
>>360 詳しく書くの面倒だけど、
結局のところ
>>360 自身も良く理解していない人ということはわかった。
~>echo $0 bash ~>echo $SHELL /bin/bash
SHELLは全部大文字 そして、echo $SHELLが正しい
$0の例外を指摘するならより実用的な方法を示してくれよ 例外ないものなんてないし 今のところ他の方法よりはマシに見えるけど
zshとかかえされてもw /usr/local/bin/zshってかえしてもらわないと
見当外れの指摘で否定したつもりの
>>313 が哀れ。
俺みんな知らないの知ってるんだぜみたいなつもりだったんだおろうが なぜそうされないのか、大方理由があるもんだ、素人がいきがっても墓穴ほるだけ echo $0つかえば?wwwwwwwwwwwww
シェルの名前だったら、大文字、Zsh パスなら絶対パス
そろそろサマリを
久しぶりにこのスレを覗いてみたらレベルのクソ低いやりとりに泣いた
仕事だったら、echo$0なんていってるやつがうんちく語り出したら 軽く流せないとな
echoとか言っている時点でアホ
意味不明文章作成スクリプトが襲来しているだけですので スルーで。
空気読まないで質問なんですが、 ./scmizu.sh file_list と起動するとfile_listで定義してあるファイルを削除してくれるツールを作りたいんですが、 今考えてるつくりは、危なっかしい気がしてならないです。 具体的にはどこが危険だかわからないんですが 考慮すべき点を指摘してくれるうれしいです! file_listの内容 sh-3.2$ cat file_list /tmp/hage/??? /tmp/hoge/??? /tmp/hoge/hammer.hammer scmizu.shの内容 #!/bin/sh # 引数チェック 省略 # 引数のファイルチェック 省略 # 処理 rm -vf `cat $1`
378 :
名無しさん@お腹いっぱい。 :2008/12/03(水) 06:07:50
危ない以前に間違ってないか?
379 :
名無しさん@お腹いっぱい。 :2008/12/03(水) 06:10:14
こうするべきだろ。 for file in `cat $1` do rm -r $file done
>>378 別に間違ってはいない。
>>379 そう書き換えても解決にならない。
>>377 ファイルリストの中にスペースを含むものがあると正しく削除されなかったり、
別の(削除してはいけない)ファイルが削除されたりする、というのが問題。
381 :
名無しさん@お腹いっぱい。 :2008/12/03(水) 07:22:14
お願いします。 以下のスクリプトを実行してみたのですが、エラーがでました。 --------------------------- $ cat hoge.sh #!/bin/sh hoge= if [ $hoge = 10 ]; then echo hello fi --------------------------- エラーの内容は、 --------------------------- $ ./hoge.sh [: =: unexpected operator --------------------------- です。 文法的に問題ないのに、なぜ、エラーになるのかわかりません、、、orz
>>381 >>381 hogeの内容が空だから、
if [ = 10 ]; then
となって testコマンドから見るとエラーになる。
if [ "$hoge" = 10 ]; then
とすること。
>>377 そのファイルリスト中のファイルの所有者は自分(root?)だけ?
他人所有のディレクトリ内のファイルでそれをやると危険。
>>377 (IFS="";
while read x; do
rm -vf "$x"
done < file_list)
-rがあるreadなら付けた方がいいです。 \や改行が含まれるパス名がある場合のみですが。
【シェルスクリプトについて】 シェルスクリプトは、短く書けるが、後で可読性が悪い。 他人の書いたシェルスクリプトを解読するためには、予め、 言語仕様を幅広く勉強しておく必要がある。 例えば、"$(cat file)" が `cat file`と同じ意味だと分かるのは、 ある種の幸運が必要だ。この手の物は、本やネットでも検索しよう がないから。 文脈で記号の意味が変動しやすいことも理解を難しくする。 "$variable"は、変数が展開されるが、'$variable'では展開されない。 ならば、`cat $variable` ではどちらか・・・。推測不可能だ。
>>386 "$(cat file)" は `cat file`と同じ意味ではない。
よってこの文章読む価値なし
PATH = xxxx:$PATH export PATH ↑これもややこしい部分。 左辺では、PATHと書くのに、右辺では$PATHと書く。exportでは、 再び$を書かない書き方。よく考えれば分からないわけでもないが、 同じ変数なのに場所によって変わってしまうのは分かりにくい。 また、=があれば代入だとみなされるらしいが、外部コマンドの 呼び出しと余りにも微妙な差しかない。 また、シェル変数と環境変数の二つに分かれているので、exportが 必用。しかし、どちらも$変数名で参照できてしまう。 そして、シェル変数は小文字、環境変数は大文字なのに、なぜか、 シェル変数にpathがあり、環境変数にはPATHがあったりする。
>>389 マジで知らないの?
>>386 自体、ネタだと思ったんだけど。他にも突っ込み箇所多数。
>>387 "$(cat file)" と同じなのは "`cat file`"
`cat file` と同じなのは $(cat file)
>>388 > PATH = xxxx:$PATH
↑ この代入文自体が間違い。
これ、誰が書いた文章よ?
程度が低過ぎるから、間違い文章貼るのやめてくれるかな
>>380 では、つっこみ箇所につっこんでみて。
>"$(cat file)" と同じなのは "`cat file`"
>`cat file` と同じなのは $(cat file)
なるほど。それはそうなんだろうけど、それらの違いは
具体的になんでしょう?
>>386 >文脈で記号の意味が変動しやすい
↑
間違い。記号の意味は変動しない。
ただ
>>386 が ' ' と ` ` を混同してるだけ。
> `cat $variable` ではどちらか
↑
どちらでもない。
$variable自体はクォートされていないから、
"$variable" でも '$variable' でもなく、
$variable として展開される。
外側の ` ` は、$variableの展開とは別物。
>>392 たとえば、
$ echo `cat file`
とやると、fileの中の改行も、2個以上のスペースも、
ひとつのスペースに変換されて、全体が1行になって表示される。
ファイルの中に * とかがあったら、カレントディレクトリのファイル名に展開される。
$ echo "`cat file`"
なら、そのような変換は行なわれず、
ファイルの内容がそのままechoされる。
いずれも、このスレの回答者にとっては常識中の常識だから、
あまりスレのレベルを下げないでくれ。
>>393 >>文脈で記号の意味が変動しやすい
>↑
>間違い。記号の意味は変動しない。
いいえ、この主張自体には間違いはない。
例えば、
ダブルクォーテーション中では、「$変数名」は展開されるのに、
シングルクォーテーション中では、「$変数名」は展開されない、
という様な事が、文脈によって「$変数名」の意味が変わっていると
みなせる。
もう一つの例としては、
=の左辺では、単に「変数名」と書くだけで変数名とみなされる
のに、右辺では単なる文字列とみなされてしまう、という事が
ある。これも「文脈」によって、解釈の方法が変わっている事の
例。例えば、C/C++/JavaやBasic言語などではこのような扱いは
ありえない。
>>386 > 【シェルスクリプトについて】
最低限の言語習得も怠ったうすら馬鹿の書いた文章。
>>391 間違い箇所は?
=の前後にスペースがあること?
>>395 たった2000行しかないマニュアル(man)読めば書いてることだよ。
お前馬鹿だろ。
>>384 それだと、fileの中の /tmp/hoge/??? というファイル指定が
文字通り ??? というファイルを指定してしまいます。
(3文字名のファイルを指定したい)
eval "rm -vf $x"
>>395 >ダブルクォーテーション中では、「$変数名」は展開されるのに、
>シングルクォーテーション中では、「$変数名」は展開されない、
↑
その意味で言うならC言語でも同じことだろ。
C言語で、
「!var」は変数varの否定演算になるが、
「"!var"」は、単なる文字列になる。
ダブルクォーテーションがあるかどうかで、「!」という記号の意味が
「変動」してるなw
あと、C言語で、
"A" と 'A' の意味も違うしな。
>>400 それだと、スペース入りファイル名の問題が再発します。
>>395 > =の左辺では、単に「変数名」と書くだけで変数名とみなされる
> のに、右辺では単なる文字列とみなされてしまう、
Cでも、左辺値と右辺値は区別されている。左辺値になれない式が存在する。
Cでも文脈によって意味が変わるということだ。
>>1 「文脈で変動している」
と言っても、コンピュータにはとっては筋が通っており、解析自体が
不可能なわけではない。
しかし、問題は、そのような例外が多くあると、シェルスクリプトの
初心者が他人のスクリプトを見た時に混乱しやすいことと、意味を調べ
たくても、検索し辛いことにある。
・「(英)単語」であれば検索しやすいが、記号だとしづらい。
・文脈依存性が強いと、調査に時間がかかる。
>>403 変動はしているが、x に x + 1 を代入したい時は素直に、
x = x + 1;
と書けばよい。一方、シェルスクリプトでは、複雑なことになる。
evalやらを使うんだと思うが。
>>388 の言いたいことがわからんでもないけど
もともとシェルはコマンド実行ユーティリティだから
普通のプログラム言語っぽく使えるだけて満足だがなあ
つ−か、書き方によってはサブシェルになる方が問題かと
>>405 > evalやらを使うんだと思うが
↑
ハイハイ、あなたの理解度はその程度ですねw
evalは使いません。勉強してから出直してね。
>>405 bash限定でいいなら、
((x = x + 1))
って素直に書けるよ。
さらに、
((x++))
という書き方もできる。
>>408 別に自慢のために書いているんじゃなく、シェルスクリプトの問題点を
考えたいと思っているだけなのに。
evalではなく、exorか、$((xxx))だった。
>>404 > しかし、問題は、そのような例外が多くあると、シェルスクリプトの
> 初心者が他人のスクリプトを見た時に混乱しやすいこと
↑
自分が理解できていないことを「例外」ということにしたいのですね、わかります
exor ---> expr
ここは、言語の根本問題とかを議論できる場ではなかったかな。 勉強不足であろうがなかろうが、言語に問題があるかどうかが 議論したかったのに。
>>414 そういうことを本気で議論したいなら、
まずは一通りでもその言語(シェルスクリプト)を習得してからじゃないと。
(批判しているつもりが、勉強不足のせいで批判ポイントがずれているしね)
>>386 のような間違いだらけの文章を書いたのでは、
どこに行っても誰にも相手にしてもらえないよ。
「間違いだらけって」言っても、 $(cat file) と "$(cat file)" の違いだけじゃん。
それだけじゃないよ。 面倒だから、間違い箇所を挙げるだけにするよ。 (1)まず、 >"$(cat file)" が `cat file` (2) >本やネットでも検索しようがないから。 本の索引で記号は検索できる。 あと、man sh (man bash) でも lessで検索できる。 (3) >文脈で記号の意味が変動 しない (4) >ならば、`cat $variable` ではどちらか そもそも、' 'と ` ` の意味を理解していない。 「どちらか」という問い自体が間違い (5) >推測不可能だ マニュアルに載ってる。推測なんて不要。
(6) >PATH = xxxx:$PATH スペースを入れちゃ駄目 (7) > =があれば代入だとみなされる というわけでもない (8) >シェル変数は小文字、環境変数は大文字 とは限らない (9) >シェル変数にpathがあり そんなものない ざっと挙げても9箇所間違い。もっと細かく見ればもっと間違いが出てくるだろう。
あんたは、頭が固いだけじゃん。
よしんば文章内に間違いがあったとしても、間違いを含む文章だから議論の価値なしとして切り捨てるのは下だわな。
単語である点として間違っているのと、議論の筋である線として間違っているのは別だろうに。
しかし
>>386 の言うような問題があるとして、今更仕様を変えられるわけでもなし…
他人に理解しにくいように書けというならばどの言語でもできるのだから、
"シェルスクリプトにおいて可読性の高めるためにはどのようにすればよいか?また、スレの住人はどのような工夫をしているか?"
というのが妥当な議題になるのか。
>>417 >(2)
>>本やネットでも検索しようがないから。
>本の索引で記号は検索できる。
>あと、man sh (man bash) でも lessで検索できる。
検索できません。試しに、Googleで、$(cat file)や、
"$(cat file)"を検索する方法を明示してください。
>(3)
>>文脈で記号の意味が変動
>しない
しまくってます。C/C++/Java の様な言語と比べれば雲泥の差です。
詳しくは知りませんが、シェルスクリプトは、「文脈依存文法」とでも
呼ぶべき様な言語に属すると思います。
>(4)
>>ならば、`cat $variable` ではどちらか
>そもそも、' 'と ` ` の意味を理解していない。
>「どちらか」という問い自体が間違い
理解してます。その上で、バッククォーテーションの中で、$varが展開さ
れるかどうかは、マニュアルを読まないことには推測できないと言っている
わけです。
>(5) >>推測不可能だ >マニュアルに載ってる。推測なんて不要。 マニュアルに載っていたとしても、推測できる言語と出来ない言語では、 分かりやすさが全く違ってきます。Makefile なども非常に頭の良い人でも マニュアルを読まずして推測するのが難しい構文が多いのです。 マニュアルを読まずして推定できる、と言う言語仕様を開発するのは、 ある種の力量が必要なのです。 >(7) >> =があれば代入だとみなされる >というわけでもない シンボル名= で、代入と見なされるはずです。違うというなら、それはそれで 文脈依存性が強い言語と言うことになりますが。 >(8) >>シェル変数は小文字、環境変数は大文字 >とは限らない >(9) >>シェル変数にpathがあり >そんなものない これについては、シェルの種類に依存するようです。
>>420 文章の間違いって、許容できるのは漢字の間違いとか、そういうレベルのことだろ。
議論の筋の根幹にかかわる部分で理解不足による間違いがあれば、
議論をしてもポイントずれまくりで話にならない。
シェルスクリプトについて教えて欲しいなら、
素直に「教えてください」って言えよ。
議論ふっかけを装って、実は自分の理解不足なところを質問したいだけだろ?
>>421 > 理解してます。その上で、バッククォーテーションの中で、$varが展開さ
> れるかどうかは、マニュアルを読まないことには推測できない
↑
それは「バッククォーテーションを理解していない」という。
そもそも ` ` と $var の展開は別物なんだから。
425 :
386 :2008/12/03(水) 13:46:49
>シェルスクリプトについて教えて欲しいなら、 >素直に「教えてください」って言えよ。 >議論ふっかけを装って、実は自分の理解不足なところを質問したいだけだろ? 違います。シェルスクリプトの問題点を整理し、新しい言語仕様の策定に 役立てたいと思っているだけです。確かに、現状のシェルスクリプトにつ いての理解も不十分ではありましたが。その点については反省します 「文脈依存性」について、考えてみましょう。 `xxx`は、コマンドxxxを実行し、その標準出力の結果をそこに展開する、 という意味です。しかし、これも、もし、 expand_stdout("command aaa${var}bbb") expand_stdout('command aaa${var}bbb') と書くのであったならば、マニュアルを読むことなく、${var}が展開 されるかどうかが一目瞭然であったんです。 これを、バッククォーテーション一つで実現しようとしたこと自体に 問題があるのではないでしょうか?
426 :
386 :2008/12/03(水) 13:49:03
>>424 仕様を知りませんが、
`"command ${var}"`
で${var}を展開できるんですか?すか。
だとすると、今度は、double quotation が back quatationの中で
「展開される」
という事実がマニュアルなしでは推定できません。
427 :
386 :2008/12/03(水) 13:54:37
「文字列中のパラメータ・ラインとして展開する」 --->expand_param("文字列") 「文字列をコマンドとして実行し標準出力を展開する」 --->expand_stdout("文字列") もし、こういう仕様であったなら、 "$(cat file)" は、丁度、 expand_param(expand_stdout("cat file")) というように書け、なんの推定の余地もないはずだったのです。 もしこうであったなら、マニュアルを読まなくても、色々な展開パターン を好きなように書けます。展開の順序も推定の余地がありませんし。
428 :
386 :2008/12/03(水) 13:55:32
誤字訂正: 「文字列中のパラメータ・ラインとして展開する」 ---> 「文字列をパラメータ・ラインとして展開する」
429 :
386 :2008/12/03(水) 13:58:41
>>427 の例とは逆に、
>>426 のように、変数を展開してからバッククォーテーション
を実行したい、という場合ならば、
expand_stdout(expand_param("command $var"));
で書けるわけです。この場合、""や``の中で色々な記号が「展開」される
かどうかを憶えている必要もないし、マニュアルを読み込む必要もありま
せん。
シェルっていうのは、本来はインタラクティブな目的のためのもので、 記述量を多くして読みやすくするための言語じゃない。 前提知識なしに読みやすくしたいなら、外部コマンドを呼ぶにも、 execute_external_command("ls", "-l"); と書くような言語を作らないといけない。 他の適当なスクリプト言語使っとけと。
432 :
386 :2008/12/03(水) 14:01:35
>>431 「本やネット」で検索できるかどうかを論じているわけです。
ネットで検索する場合、Googleで検索可能でないと、いったい何で
検索可能なんでしょうか?
記号単独の検索でも難しいのに、文脈依存性が高い言語仕様の場合、
探し出すのに非常に時間がかかります。
433 :
386 :2008/12/03(水) 14:02:30
>>430 結局、そうなんです。
コマンドラインで短く打つ事と、わかりやすさのトレードオフになって
くるんでしょう。
んじゃ、仕様が完成したら、ここに報告に来てくれ。
435 :
386 :2008/12/03(水) 14:05:18
いや、ここで議論したい。
で、トレードオフの結果が、今のシェルだ。 100歩ゆずって、plan9 の rc だ。 もっと勉強しろ。
437 :
386 :2008/12/03(水) 14:07:03
>>436 今のシェルは、トレードオフの仕方が「下手」であったと考えます。
plan9のrcは知りません。
>>437 お前の頭の悪さには負けるよ。
仕様も理解せずに批判しようと言うのだから。
レベルが低すぎて話にならない。
30年も現役の言語を、 30分で読めるsh(1)さえ読まずに、 批判しようと言うのが間違ってる。
30年も現役であっても、このような劣悪な状態であったのは、市場が 閉鎖的であっただからか。
ここは30年も使い続けられたクソ仕様の sh を 無理に延命させるスレということでいいよ。 まったく別の言語仕様のシェルがほしいって話なら perl でも emacs でも好きなものを chsh で設定すればいいじゃないか。 このスレでやることじゃない。
コマンドラインで短く打てて、インタプリタ方式だから試行錯誤が容易。 素人でも頑張ればなんとかかんとか使える敷居の低さが普及の最大の要因だと思う。 ところでシェルスクリプトとは全く別のスクリプトの策定に協力しろなどというのはこのスレの趣旨とは違うだろ。 シェルスクリプトで可読性が低いな、とか不便だな、とか思ったことはありませんか?と情報を集めるならばまだしも、議論を求めるのはお門違いだ。
かつてあった(今もある?)OSつくろうスレみたいに、 シェル作ろうスレ立てて、 絶対投げ出さずみんなをひっぱっていくくらいの気概があるなら、 ついていくやつもいるんじゃなかろうか。 ここはそういう場ではないということだ。
シェルスクリプトに大きな不満は無いな。 劣悪な状態だなんて思ってる人いる? がっちり書きたいならperlなりなんなり使えばいいだけだし
UNIX/Linux界隈でPowerShellみたいなものが主流になることは俺が生きてる内は無いだろうな
Powershellが現行シェル(sh,bash.tcsh,zsh)より優れている点ってなんじゃい? Windowsとの親和性が高いことの他にだが。
後発だけあってPowerShellの「仕様は」強力でよくできてると思うが コマンドインタプリタ/スクリプティング用途には起動が致命的に重くて 俺には使い道が無い .NETやJava系は、そのプロセス起動の重さのお陰で Unix流のツールボックスアプローチ的使い方には 全く不向きなプラットフォームだと思っている 計算性能においてははるかに劣るLLの方が、マシ
GoogleがHotなんとかとかいうチト変わったシェル作ってなかったっけ?
450 :
>>381 :2008/12/03(水) 23:37:48
>>382 ありがとうございます。
ふと思ったのですが、数値比較の場合、どのようになりますか?
----- コーテーションなし------------------------------------
$ cat hoge.sh
#!/bin/sh
hoge=
if [ $hoge -eq 10 ]; then
echo hello
fi
$ ./hoge.sh
[: -eq: unexpected operator
----- コーテーションあり--------------------------------------
$ cat hoge.sh
#!/bin/sh
hoge=
if [ "$hoge" -eq 10 ]; then
echo hello
fi
$ ./hoge.sh
[: : bad number
どっちにしても、エラーがでる、、、、orz
半日でえらくスレが消費されてて、 おそるべきはニートだなと改めておもった
>>450 一体何をしたいんだ?
純正シェルでも使えるのか知らんが、適当にデフォルトの値(ここでは0)を決めておいて
${hoge:-0}
と書けば、hoge が宣言されていないか、宣言されているが値が無いときに 0 に評価される
数値以外をはじかなければエラーがでる。
454 :
>>450 :2008/12/04(木) 07:03:48
455 :
名無しさん@お腹いっぱい。 :2008/12/04(木) 08:35:29
sedで質問です。 sedの置き換え文字列に改行を含む場合、以下のようになります。 hoge() { echo "start" sed 's/hoge/foo \ bar/' echo "end" } しかし、これですと、インデントがそろわず、不恰好になります。 インデントをずらす方法はないでしょうか?
気にすんな。
>>455 sedの内容を、シェル関数外でシェル変数(regex)とかに代入しておいて、
シェル関数内では sed "$regex" と書けば良い。
>>456 気にしろ
bash/GNUツール前提でいいよ あと最近は、OSXのやつらの台頭でスペース文字含みのファイルとか 余裕で出てくるようになったからその辺を気にしないといけなくなった
sed `echo 's/hoge/foo \ bar/' | sed -e 's/ //g'` 二行目はhtab使ってるから注意しな。
見た目を気にするならもっとまともな言語使え。 マニュアルを読まないと推定できないような言語じゃなくて。
>>459 だから、インデントのいらない階層であるところの「シェル関数外」で
regexに代入するんだろ。
もともとインデントゼロのスコープに書くんだから、
不恰好にならない。
頭使え。
>>455 N='
'
hoge() {
sed "s/hoge/foo ${N}bar/"
}
>>456 気にしろw
あ、
>>463 のsedの ${N}の前にバックスラッシュ入れてね。
なぜかこの環境から書き込むとバックスラッシュが化けるので、、
ダブルクォートの中だからバックスラッシュは2つね。
465 :
名無しさん@お腹いっぱい。 :2008/12/04(木) 23:01:38
新しい2ch語誕生の瞬間? ってほどでもないかw
467 :
名無しさん@お腹いっぱい。 :2008/12/06(土) 11:20:20
>見た目を気にするならもっとまともな言語使え。 >マニュアルを読まないと推定できないような言語じゃなくて。 シェルスクリプトすら書けないんなら、この業界から足をあらってカタギになれ!
マニュアル読んだら推定じゃなくて理解してくれ。
>マニュアルを読まないと推定できないような言語じゃなくて。 マニュアルを読んでも推定しかできないんなら、カタギになれ!
マニュアルが完全じゃないこともそれなりにあるのがUnix
471 :
名無しさん@お腹いっぱい。 :2008/12/06(土) 13:06:54
`いいからカタギになれ
ああちくしょう。超バカーなスクリプト書いてしまった↓ FOUND=false netstat -lnx | grep /tmp/ssh | while read i; do set -- $i if [ -O "$9" ]; then SSH_AUTH_SOCK=$9; export SSH_AUTH_SOCK SSH_AGENT_PID=`echo $9 | cut -d. -f2`; export SSH_AGENT_PID FOUND=true fi done $FOUND || eval `ssh-agent -s` シェルスクリプトでwhileはサブシェルなのだと何回やれば判るのかと・・・
s/while/|while/; #今日はもうダメポ。寝る!
文字列を返す関数を作るのが定石かと。
shをインデントするツールないの?
Emacs
vim
479 :
名無しさん@お腹いっぱい。 :2008/12/07(日) 15:29:09
gedit
vim /bin/sh ってやったら文字化けしましたが…
vim -b /bin/sh -c '%!xxd'
vimやemacsでどうやってインデントするのか教えてください!
いやです
>>455 もう質問者いなそうだけどOSによっては改行として"^J"を使う手も
vi だと挿入モードの時、ctrl + v してから ctrl + j で入力
sed 's/hoge/foo \
bar/'
を
sed 's/hoge/foo ^Jbar/'
OSを選ぶので汎用性もないしオプションなしのcatやmoreだと"^J"の部分が
改行になるかもと色々問題ありまくりだけど場合によってはこんな方法もってことで
あと"^J"使える場合はヒアドキュメントも cat - <<END^JOK^JEND と1行で書ける
意味あるかどうか人それぞれだろうけど
OSというかshellの問題。 改行扱えないsedは存在しないんじゃないかな。
>>485 そういう問題じゃないんだよ。
もとの質問の
>>455 よくよめ
UNIX環境では ^J は改行そのものなので、
>>484 の方法では全く解決にならない。
GNUの奴なら\nでいいのにーとかいう話? ぶっちゃけPerl使えばいいんじゃね?
489 :
487 :2008/12/08(月) 22:49:22
>>488 あ、ごめん、俺のは横レスだから
>>485 あたりの人とは別人
>>455 見る限りでは、GNUではないsedだから置換文字列に\nが
使えなくてああいう書き方をしてて、それがいやだってんでしょ?
そう読めたけど
ssh-agent 使えって示唆が出ているが?
2スレ並列でやる必要もあるまい。
AIXに導入するシェルを作ってるんですけど・・・。 if [ 変数 != 文字列A ] | [ 変数 != 文字列B ];then ERROR処理 fi ネスト無しでやる場合これって有りかな? 数値じゃないから-oは使えないんでこれしかやりようがなかったんすけど 有識者の方頼みます
>>494 | じゃなくて || な。
↓
if [ 変数 != 文字列A ] || [ 変数 != 文字列B ]; then
あと、数式じゃなくても -o 使えるよ。
↓
if [ 変数 != 文字列A -o 変数 != 文字列B ]; then
-o が使えないのは [[ ]] の場合。その場合は、
↓
if [[ 変数 != 文字列A || 変数 != 文字列B ]]; then
しかし、「変数」が同じ変数なら、 意味的には、やりたいことは -o (||) じゃなくて、-a (&&) のような気がする。
>>494 この場合、if [ ] よりも case を使った方が簡単に書けるよ。
>>495 実は|でいけたんっすよ
テストケース作って試したんですけど、一応正常系も異常系も通りました。。。
-oについては明日また試してみます
ありがとうございます
>>497 ミドルのステータスチェックを増やしたんすよ
元が共通シェルだから余り大幅な変更は出来ないんです
caseの方が良いのはその通りなんですが・・
>>498 行けたように勘違いしただけで正常に変数チェックされていない。
| は パイプ。パイプでは、A | B の場合、Bが真か偽かしかチェックされない。
(Aは無関係になる)
具体的には、
if [ 変数 != 文字列A ] | [ 変数 != 文字列B ];then
だと、
[ 変数 != 文字列B ] だけがチェックされて、
[ 変数 != 文字列A ] の結果は無視される。
それをたまたま「行けた」と勘違いしただけ。
全然行けてないので勘違いしないように。
「シェル」を作っているのですね?
簡単なコンソールゲームを作りたいんですけど 下の1から3に画面を変えるときは clearして全部表示しなおすしかないですかね? 表示しなおしたい部分だけ変えるってできないのかな? 1. □■□ □□□ □□□ 2. □□□ □■□ □□□ 3. □□□ □□□ □■□
ANSI系端末決め打ちなら、 エスケープシーケンス出力してカーソル動かせばいい。 zshならcursesモジュールがあるから端末独立なスクリプトも書けるだろうけど。
>>503 tput使え。
例えばtput cuu1がカーソルを一行上げる。
tput homeで左上へ移動。
>>503 シェルでは無理。
強いてやるなら、echo;echo;echo;echo;.... で画面を全部流してから、
新しい画面の文字を全部 echoし直すしかないかな。
tput cup ROW COL
カーソル移動がcupかどうか(というか、terminfoかtermcapか)は、OSによる。 FreeBSDならcm。
的外れかも知れないけどエスケープシーケンス使ってグリグリ書くのは駄目なん?
>>509 tputって OS間の互換性ないんだな。
「HP-UXの質問はココだ No4」から移動してきました。 HP-UX11iv2orv3でファイルをある一定の法則に従う複数のディレクトリにコピーするコマンドについて お知恵をお貸しください。 たとえば、下記のようなディレクトリに同一のファイルを配置したいのですが 論理ホスト名が異なるサーバでも同じコマンドで実行できるようできませんか。 /etc/opt/論理ホスト名1/sh/ /etc/opt/論理ホスト名2/sh/ /etc/opt/論理ホスト名3/sh/ RHELの場合、下記コマンドで実行できたのですが HP-UXでは、{}を単独で使わないと、検索したパスに置き換えてくれないようです。 (下記記述だと{}を{}そのもので認識されてしまいました。) find /etc/opt/ -type d -path */sh -exec cp 配布元ファイル {}/配布先ファイル \; 配布元ファイル名と配布先ファイル名は、異なる場合でも対応できるようにしたいです。 よろしくお願いします。
>>512 for dir in /etc/opt/*/sh
do
cp 配布元ファイル $dir/配布先ファイル
done
514 :
512 :2008/12/15(月) 23:07:52
>>513 レスありがとうございます!!
forは思いつきませんでした
HP-UXではtreeコマンドがないので、以下のシェルで代用しているのですが
http://ash.jp/ash/src/csh/tree.txt どうせならファイルの詳細情報も表示させたいと思っています。
今のままだと以下の表示なのですが、
+---bin/
+---boot/
| +---efi/
| | +---EFI/
以下のように表示させたい。どうすればよいですか?
+---bin/ drwxr-xr-x 2 root root 4096 2008-12-21 16:11
+---boot/ drwxr-xr-x 5 root root 1024 2008-10-26 05:21
| +---efi/ drwxr-xr-x 13 root root 4200 2008-12-21 16:03
| | +---EFI/ drwxr-xr-x 115 root root 12288 2008-12-21 16:11
あんたは、たとえばawkスクリプトであっても 「以下のawkで代用しているのですが」みたいに書くのか?
>>516 すみませんが、質問だけに答えてください。
.| ./川\ | \/┏┷┓\/ 。┃お┃。 ゙ # ゚┃断┃; 。 ; 。 ・┃り.┃・ # 。 ;゙ #┃し.┃# 。 ゙・# : ┃ま┃。 ; 。 .;:# ゙。゚┃す┃゚ 。 # ; 。;; ゙.:。┗┯┛。 # : # . ハ,,ハ | . ( ゚ω゚ ) | :/ つΦ
>>519 シェルで代用もご存知ない方には聞いていません。
ハイ、次のもっと優秀な回答者
↓
この慇懃無礼な書き込み以前もどこかで見たような? Emacsスレか?
find . -ls で我慢しなさい
cshだよ!
シェルってゆうな。クズ。
525 :
名無しさん@お腹いっぱい。 :2008/12/22(月) 15:25:41
FreeBSDのサーバーには freeコマンドがなく、 不便なのでシェルを作ろうと思うのですが、 具体的にはどう作ればいいですか?
そういう釣りはやめれ。
カレントのディレクトリのを見て各ディレクトリの階層がいくつあるのかを出力したのですが うまいこといきますか ちなみにディレクトリ名は日本語だったりスペースありだったり()あったりです。
日本語があれでよくわからんが、 改行がないなら、findして、/の個数を数えて、最大値でも出せばどうかね?
まずカレントにあるディレクトリのリストが取れないです。 find ./ -type d だと再帰的になってしまうので ls -l | egrep '^d' | awk ' { print $8 } ' みたいにしたら、スペース込みのディレクトリ名の場合8カラム目以降消えてしまうし
-depth のない find か?
-depthというの初めて知りました・・ ちっと出直してきます
おいおい、-depthがあるfindでも無理だろ。 (-depthはあっても-maxdepthがないfindは存在する)
まずはカレントディレクトリ直下のサブディレクトリを列挙したいんだろ。 -depth 1 -type d で要求は満たす。 -maxdepth 1 を指定すれば効率はよくなるだろうけど、 ないと無理という根拠が不明。
>>533 おいおい、何か勘違いしてないか?
-depth に引数は付かない。
全く要求を満たさない。
試してから書けよな。
たぶん、
>>533 は、FreeBSD方言の-depthのことを言ってるな。
一般のfindの-depthじゃ、
>>534 の言う通り、無理なんだよ。(例:Solaris)
GNU find にも -depth n がないのか。俺が悪かったわ。
-maxdepth nはあるが。
find -depth n ってBSD方言だったのか。。。知らなかった
>>536 はいって何?
出来るの?
さっきから何度も。
はいって言葉の重みわかってる?
いま出来ますって断言したんだよ君。
その責任の重さわかってんの?
社会に出たらもっと自分の言葉に責任持てよ。
ん?
社会人の一言一言に掛かる責任の重さが分かってないだろ全然。
学生気分でやってんだったら帰ってもらうよ。
とにかく明日はもう来なくていいから。
ワイルドカードを展開して test で調べるんじゃだめなの?
シェルスクリプト(bash)を勉強するのにお勧めの本ありますか?
>>543 標準bourne shellにこだわらなければ、
.で始まるファイルをファイル展開に含める方法があるシェルが最近は多い。
(不正確な記憶) .[^.]* * とか書けばいいんじゃなかったけ?
>>545 ..aaが含まれない。
.* *で.と..を省いた方がまだいい。
ls -A -F | grep '/$' | sed s/\\///
結局ディレクトリが空か見るのって find hogedir -type f | wc -l とかしか無いの? かっこいいのないのかね
ls -A hogedir | wc -l の方がましでは?
>>548 hogedir 以下にディレクトリがあっても空とみなすの?
551 :
名無しさん@お腹いっぱい。 :2008/12/27(土) 04:20:31
文字列置換え処理で質問です!以下の3つのファイルがあるとします。 $ cat a.dat 111 AAA BBB CCC 222 $ cat b.dat AAA BBB CCC $ cat c.dat DDD EEE FFF で、以下のように実行(hogeコマンドはあくまでイメージです)すると、 ------------------------- $ hoge -t a.dat -s b.dat -d c.dat 111 DDD EEE FFF 222 ------------------------- 上のようになるコマンドはありますでしょうか? そのようなコマンドがない場合、みなさんだったらどのようにこの置換えを行いますか?
-tのデータで、 -sにあるものを 対応する-dの行で置き換えるってこと? $ cat b.dat BBB AAA なら、 111 EEE DDD CCC 222 ってこと?
特定の例だけひっぱりだすんじゃなくて、言葉でちゃんと説明しろ
>>549 case `ls -A hogedir` in '') 空の場合の処理;; esac
の方が、wcがいらない分まし。
555 :
名無しさん@お腹いっぱい。 :2008/12/27(土) 14:40:01
>>552 違います。すいません説明がたりませんでした。
ある領域に一致するものを、別の領域に置き換えるという意味です。
>>552 の場合は、一致しないので置き換えないようになります。
説明になってねえよ
エスパーすると、 b.datの内容(3行全部)に完全に一致する部分を、 c.datの内容で置き換えるってことか。
リンク数が2、というのは空ディレクトリの判定方法として 妥当だろうか。 ディレクトリのハードリンクについては考えないことにする。
ディレクトリであって、かつリンク数が2ってことね。
リンク==2 → ディレクトリを含まないディレクトリ (通常ファイルはたくさんあっていい)
手元でやってみたら、 MacOS XのHFS+→ファイルを作ると . へのンク数+1 Linuxのext3→ファイルを作ってもリンク数は増えない となった。
563 :
名無しさん@お腹いっぱい。 :2008/12/27(土) 20:57:40
>>558 おおむね妥当というか、定番の方法。
ただし、ダメなことがあるので、そのショートカットは省略できるように
色々なツールがオプション持ってるけどね。
>>564 なんでやねん。
それは、ディレクトリが「leaf」かどうかを判断する方法であって、
「空」かどうかの判断にはなっていない。
ディレクトリ中に普通のファイルが存在しても、リンクカウントは2のままなんだから。
しまった、空かどうかの話か。すまん。 それだとrmdirしてみるくらいしか思いつかないなぁ。
rmdirは親ディレクトリに対する書き込み権限が無いと判定できない。
一瞬でも消えると健全性が失われる可能性がある。
>>563 awk駆使するしかないかなー。
何気にあってもいいような気がするんだけど、そんなコマンドないんだよねー。
571 :
名無しさん@お腹いっぱい。 :2009/01/05(月) 01:38:25
すいません質問させてください。 /home/hoge ディレクトリにある全てのファイルの改行コードを全部LF変更して上書きするシェルスクリプトを書きたいのですが、どう書けばよいでしょうか?? nkf -w -Lu samble.txt > sample.text のようにやればよいのは知っているのですが、全ファイル一気に処理したい場合どうすればよいか分かりません。 ご教示いただけると幸いです。
572 :
名無しさん@お腹いっぱい。 :2009/01/05(月) 01:39:17
LF変更 ↓ LFに変更 です。。
>>571 > nkf -w -Lu samble.txt > sample.text
> のようにやればよいのは知っているのですが
あかんで!
perl -iでも使えば。Encode/jcodeで変換して。
シェルスクリプトなら、
for i in *.txt; do
nkf -w -Lu $i > $i.--$$--
# 必要ならば yes no | mv -i $i $i.org
mv $i.--$$-- $i
done
>>571 以下で桶。
↓
#!/bin/sh
cd /home/hoge
for file in *.txt
do
out_file=`basename "$file" .txt`.text
nkf -w -Lu "$file" > "$out_file"
done
>>573 > あかんで!
↑
なんであかんの?w
.txtと.textを読み落したか?w
上書きはしないよw
foo.textあったら無条件に上書きするなあ
--overwriteも--in-placeも無いnkfって古すぎないか? % nkf -w -Lu --in-place=.bak *.txt じゃね
>>575 それはへ理屈。
>>573 の回答を見れば、.txtを.txtに変換しようとしてるので、
質問を読み間違えてるのは明らか。
しかも、スペース入りファイル名があると正常動作しないし。
知ったか回答者の典型。
元がCRLF かLFならば tr -d "\r" < input.txt > output.txt で改行コードが変換できる。
579 :
名無しさん@お腹いっぱい。 :2009/01/05(月) 18:58:46
「ヒアドキュメントで書けるものは、必ず echo + パイプで書ける」 という命題は真ですか?
日本語でわかりやすく
>>580 は答えなくていいよ。
ハイ、次の回答者。
真
じゃあ、ヒアドキュメントはなくても困りませんね
ないとかったるいね。
複数の記法がある事に不都合はない。
チューリングコンプリートであればコンピュータは1種類でよい、という主張と 似たようなもんだな。
Whitespaceさえあればあとはいらん。
やっぱ色々使いたいじゃん perlがあってもsedやawkは使うしもちろんシェルスクリプトも使う オナニー万歳
ふつー、sedやawkは使ってもperlは使わないなぁ
goshやsbclを使う人がいるんだもの perlぐらいフツーっすよ
sedで足りるものはsedで、足りないものはperlで、awkは中途半端
sed→awk→ruby かな俺の場合 awkがメイン
まぁ、もうその辺で。
何でもphpなオレは負け組
手動で出来る事は自動化できるのがシェルスクリプトなんですが、 どうもうまくいかない。 >telnet POP3.net 110 > mail user MYID pass MYPASS retr 1 quit Connection closed by foreign host. > となりうまくいくんだけど、 telnet POP3.net 110 << EOF user MYID pass MYPASS retr 1 quit EOF というのをリダイレクトすると Connected to POP3.net Escape character is '^]'. Connection closed by foreign host. となり全然駄目。 ものすごい致命的な間違い、勘違いがありそう。 とりあえずこれから man telnet www.ietf.org/rfc/rfc1939.txt を一通り読むんですが、その前に間違いを指摘して下さいな。
telnetの代わりにnetcat(あるいはnc)を使ったらうまくいきそうな気がする。
telnetは標準入力じゃなくてttyを入出力とするからリダイレクト出来ない。
>>596 netcat,nc初めて聞きます。調べておこう。
>>597 どうも助かります。
>telnetは標準入力じゃなくてttyを入出力とするからリダイレクト出来ない
となると、
>telnet hoge.net < `tty` という具合ですね。
別の端末から
>echo "user MYID" > /dev/あっち とか。
telnetをやるスクリプトを動かすスクリプトを書いて
上位からttyへ流し込むとか。
いろいろやってみますね。
どうもサンクスです。
599 :
595 :2009/01/07(水) 02:25:51
>>596 ncで動きました。これで自動化できます。
telnetも標準入力から読むよ UNIX FAQにあるように echo と sleep で 間隔開けて1行ずつ出せばいけたかも
expect
?
604 :
595 :2009/01/08(木) 22:29:27
動いた気がしただけでした(藁 セキュリティ絡みでひっかかって駄目みたい。 ok ok ok とくるからpassまではいけてるから、そっから先に いろいろあるんだろうなあ。 ぐぐったらperlのスクリプトが沢山あったから、 参考にしてみます。
605 :
571 :2009/01/09(金) 02:21:36
563-578 御礼遅れてすいません。ありがとうございました! --overwrite なんてオプションあったんですね。知りませんでした。 あとすいません、573の方が書いてくださったシェルスクリプトの--&&-- ってのはどういう意味でなのでしょう? ご教示いただきたくm(_ _)m
FreeBSDで書いた自作シェルって、Linuxでもそのまま動くんですね!! こりゃ便利です。移行もスムーズです!!!
>>605 --&&-- じゃなく --$$-- な。
echo --$$--
ってやってみ。
別に .aho でも .baka でも .tmp でもいいんだろうが、
.bak だと同名のファイルが既に存在していて壊してしまうおそれが高いし、
.--$$-- ならその可能性は低いだろうと、それだけのこと。
609 :
571 :2009/01/09(金) 11:29:11
なるほど、プロセスIDを保持しているんですね。ありがとうございます。 すいません、あとひとつお聞きしたいのですが outfile=`basename "$file" .txt` .text で、 ""は必要ですか?? 試してみると outfile=`basename $file .txt` .text でもできました。
ファイル名に空白文字が入っている可能性がなければ不要。
>>609 " " は必要。
" "がないと、スペースとか、特殊記号を含んだファイル名で正常動作しない。
GUIやsambaが当たり前の環境ではスペース含みのファイル名は普通にあると
思った方がいいので当面必要無くても常にダブルクォートを付けるルールを守ること
その意味で
>>573 は失格
>>611 > 特殊記号を含んだファイル名
問題になるな特殊記号って?
*
おけ。把握。
&が取り込んだ曲のアーティスト名にありがち。
バッククォートはシェルが再解釈するから、(ファイル名が外からやっ てくるなら)普通にメタキャラクタのチェックしないと危険だろ。
618 :
sage :2009/01/10(土) 14:55:14
>>551 の置換えって、結局プログラムでやるしかないという結論?
>>618 そんなコマンドは見たことないな。
置き換え対象のファイルがあまり大きくないならperlかなにかで
一つの文字列にまるごと読み込んで置換するのが楽だと思う。
メモリにおけないぐらいでかいファイルなら工夫が必要だけど
>>551 今一何をしたいのかよく分からないんだけど、
a.datとb.datを評価して違っていればc.datに置き換えると解釈して書いてみた。
#!/bin/sh
File_line_digit(){
FLINE=`cat "$1" | wc -l | sed 's/[[:blank:]]*//'`
echo "$FLINE"
}
Use_line_strings(){
STRINGS=`head -n "$1" "$2" | tail -n 1`
echo "$STRINGS"
}
続く
ONENUM=1 TWONUM=1 THREENUM=1 ONEEND=`File_line_digit "$1"` TWEEND=`File_line_digit "$2"` THREEEND=`File_line_digit "$3"` while [ "$ONENUM" -ne `expr "$ONEEND" + 1` ] do ONESTR=`Use_line_strings "$ONENUM" "$1"` TWOSTR=`Use_line_strings "$TWONUM" "$2"` THREESTR=`Use_line_strings "$THREENUM" "$3"` if [ "$ONESTR" = "$TWOSTR" ] then echo "$THREESTR" ONENUM=`expr "$ONENUM" + 1` TWONUM=`expr "$TWONUM" + 1` THREENUM=`expr "$THREENUM" + 1` else echo "$ONESTR" ONENUM=`expr "$ONENUM" + 1` fi done
問題の解釈間違ってると思うけど それ以前にブログラミングのセンスなさすぎだろ 関数名も変数名も処理内容もださすぎ
ネタで書いてるものだと思ってたが、もしかして違うのか?
たまにいるなこうゆう人。 プログラム書かないでほしいよ、、今の上司とか
>>620 とりあえず、頭の関数ひとつだけ添削してやるよw
File_line_digit(){
FLINE=`wc -l < "$1"`
echo $FLINE # ここは、わざとダブルクォートを付けない
}
↑のようにすれば、wc -l の出力のスペースをカットするために
わざわざsedを使う必要がない。あと、もちろんcatは不要。
wc -l の出力にファイル名が付かないように、
標準入力からリダイレクトする。
627 :
571 :2009/01/12(月) 13:28:52
なるほど!。さんくすですm(_ _)m
俺も
>>551 に挑戦してみたんだが、
何故か思うように動かない。
考え方としては有っていると思うのだが、
最後のif文の比較がどうしても真にならない。
set -x して、トレースしたら同じ文字列のはずだし、
空白が混入しているようにも思えないのだが・・
629 :
628 :2009/01/12(月) 14:22:44
#!/bin/sh - searchLine=`head -n 1 "$2"` fullLines=`echo \`wc -l < "$1"\` ` matchLines=`echo \`wc -l < "$2"\` ` matchPat=`tr '\012' ' ' < "$2"` while [ $fullLines -ge $matchLines ] do cmpPat=`tail -n $fullLines "$1" | \ awk ' $0 !~ /^'"$searchLine"'$/ { print > "/dev/tty" } /'"$searchLine"'/{ cmpPat = $0 for ( i = 1 ; i < '"$matchLines"' ; ++i ) { getline addLine cmpPat = cmpPat " " addLine } print cmpPat nextfile }'` if [ "$cmpPat" = "$matchPat" ] then cat "$3" $fullLines=`expr $fullLines - $matchLines` else fullLines=`expr $fullLines - 1` fi done tail -n $fullLines "$1"
630 :
628 :2009/01/12(月) 14:37:35
ああ、余計な $ が、一個付いてるけど、 そもそも、そこに処理が行かないわけで・・
631 :
628 :2009/01/12(月) 14:57:09
お騒がせしました。 trが最後に改行が無くても空白を追加していました。 しかし、どうも上記はまだまだ使い物になりません。 もう少し精進します。 てか、これ、結構ムズい。
632 :
628 :2009/01/12(月) 15:29:55
連投申し訳ない。動いたかも?? #!/bin/sh - searchLine=`head -n 1 "$2"` fullLines=`echo \`wc -l < "$1"\` ` matchLines=`echo \`wc -l < "$2"\` ` matchPat=`tr '\012' ' ' < "$2"` while [ $fullLines -ge $matchLines ] ; do cmpPat=`tail -n $fullLines "$1" | \ awk ' $0 !~ /^'"$searchLine"'$/ { print > "/dev/tty" nextfile } $0 ~ /^'"$searchLine"'$/{ cmpPat = $0 for ( i = 1 ; i < '"$matchLines"' ; ++i ) { getline addLine cmpPat = cmpPat " " addLine } cmpPat = cmpPat " " print cmpPat nextfile }'` if [ "$cmpPat" = "$matchPat" ] then cat "$3" fullLines=`expr $fullLines - $matchLines` fi fullLines=`expr $fullLines - 1` done tail -n $fullLines "$1"
そんなの誰も見ないから、ちらしの裏に書いとけ
>>633 そうは言うけど、
>>551 の設問を
>>557 の要件で満たすのは大変だぞ。
現に誰もまともな解答例が無いだろう。
仮に三つのファイルを
1・対象ファイル
2・参照ファイル
3・置換ファイル
として、1の行数が不定の上、
2が何回マッチするかも不定で、
シェルスクリプト流に一行づつ処理するならば
途中でマッチしないことが判明したら、仕切り直さないといけない。
(でも、マッチしたらその分行を進めないといけない)
いっそC言語とかで書いて、2のファイルを読み出して保持しておき、
同じサイズのバッファをmallocとかで確保し、順次改行迄ごとに1のファイルを読んで、
strcmpとかする方が楽に思える。
無駄な処理が実に多いのは承知の上で、
tail と awk の合わせ技で料理したのに、
実に君は無礼だな。
複数行の置換をawkで考えたくないなあ 富豪的にrubyとかperlでやった方がマシでしょ #!/usr/bin/env ruby # -*- coding: utf-8; -*- abort unless ARGV.size == 3 open(ARGV.shift).read.\ gsub(/#{Regexp.escape(open(ARGV.shift).read)}/m,open(ARGV.shift).read).\ display まあワンライナーだよな
>>551 cat a.dat b.dat c.dat | uniq
おまいら大丈夫か?
>>635 多大なるヒントを有難う。
やっぱりawkだけで書けるわ。
#!/bin/sh -
searchLine=`head -n 1 "$2"`
matchLines=`echo \`wc -l < "$2"\` `
cmpList=`tr '\012' ' ' < "$2"`
awk '
$0 !~ /^'"$searchLine"'$/ {
print $0
next
}
$0 ~ /^'"$searchLine"'$/ {
matchList = $0
for ( i = 1; i < '"$matchLines"'; ++i ) {
getline
matchList = matchList " " $0
}
matchList = matchList " "
if ( matchList ~ /^'"$cmpList"'$/ ) system("cat '"$3"'")
else {
sizeOfArray = split(matchList, pArray, " ")
for ( i = 1; i <= sizeOfArray; ++i)
print pArray[i]
}
}' "$1"
>>639 BEGINで$1, $2のファイル読み込むといいと思うよ。
awkは(初期のを除いて)リダイレクト使えるから。
# すれ違いっぽいからコードは書かないけど
>>640 有難う御座います。
awkでの正規表現中での変数展開のやり方が分からず、
先にシェルに展開してもらう方法をとっていましたが、
今調べたり、それを元にゴソゴソやって。
$0 ~ "^"var"$" { とか
if ( var1 ~ "^"var2"$" ) で、
どうやら完全一致を取り出せそうなことが分かりました。
右辺は正規表現パターン。 右辺が文字列型の値の場合は正規表現パターンを表すとみなす。 だからawk -v arg1="XXX"{ BEGIN { searchLine=arg1 } $1 ~ searchLine { ...って出来る。 awk本のオリジナルawkは、"-v"なしで代入式だけを書かないといけないんだけど。 "-v"はnawk移行かな? 今はほとんど全部"-v"が必要なはずと思う。
searchLine="^" arg1 "$" と書いたつもりでした。
なんで上記コードでは、awkスクリプト全体の「'」と 正規表現中の「'」がうまく認識されるのですか? awk ' $0 !~ /^' ここでぶったぎられそうな気がするのですが。
>>644 ぶったぎられる、というのはその通り。
ところが、その直後にスペースを入れずに "$searchLine" と続けているから、
結局これら全体がシェル上で「1つの引数」になって awkに渡される。
>>644 単にシェルが「'」を食べるだけ。
#!/usr/bin/awk -f というスクリプトを考えたら良い。
そう言う場合は「'」は不要でしょう?。
要するに、「'」と「'」に挟まれたところをシェルがそのまま awk に渡し、
その外側の部分を、シェルが先に解釈(展開)すると言うだけの事。
最終的には全部 awk に渡される。
>>644 $set 'Path'" $HOME "' is my home.'
$ echo $1
Path /home/foo is my home.
##
$ set 'Path' "$HOME" ' is my home.'
$ echo $1
Path
$ echo $2
/home/foo
$ echo $3
is my home.
こういうことだけど。
文字列の間に空白がないから一つになってる。
>>647 むむ。
>>645 は、何も言っていないに等しいとしか読めない。
スペースの有る無しは変数名が変わると言うことだし、
awk への引数ではなく、その文脈上の展開した値として単純に awk に渡されると
認識している。
念を押すが、awk (にしろ他のコマンドにしろ)「'」の存在は知らない。
いや、正直良く分かりません。 ??
シェルスクリプト中にawkみたいな感じで ペタってコード書ける言語って、 他になにがありますかね。
スクリプト系言語で出来ない方が珍しい。 引数にコード渡せればいいだけだから。
>>649 あなた、微妙に理解がズレてますよ。
>スペースの有る無しは変数名が変わると言うことだし、
↑
じゃなくて、awkは1番目の引数の文字列内容を「プログラム」と認識するので、
シェル上ではスペースを入れないで繋げるということが重要。
>念を押すが、awk (にしろ他のコマンドにしろ)「'」の存在は知らない。
↑
そんなことは当たり前。その点が問題になってるんじゃないの。
>>648 が説明しようとしてるとおり、
awk 'awkのプログラムの前半'"$シェル変数"'awkのプログラムの後半'
と、(クォートの中を除いて)スペースを入れずに書くことが重要で、
これが awkには、
「awkのプログラムの前半」と「$シェル変数の中身」と「awkのプログラムの後半」
が連結されて「1つの引数」として渡される。「1つの引数」が重要。
元の
>>644 の質問では、1つの引数の引数になるべきところの途中で
つまり、「awkのプログラムの前半」の最後で一旦シングルクォートが閉じているのに、
なぜそこで引数が分断されないのか? という質問。
それに対して
>>646 の回答はズレている。
最初の
>>645 の回答が的確。
どっちも言い方は違うけど 間違ってないと思うょ 真っ赤になって相手を否定するのこそ間違ってる
>>649 氏は、
「
>>645 は、何も言っていないに等しいとしか読めない。」
なんて発言しちゃってるから、
>>645 の意味が理解できてないみたいだね。
>>645 の解答が出た後で、
なんでピンボケな
>>646 のカキコがあるのか不思議に思ってた。
あと、
>>649 氏の発言をもうひとつ指摘、
「スペースの有る無しは変数名が変わると言うことだし」
もしかして、『変数』と『引数』の用語を混同してますか?
もしスペースがあって、awkプログラム部分が複数の『引数』に分かれてしまうと、
そもそもawkは正常動作しませんよ。変数名が変わるだけの問題では済みません。
>>656 >>
>>645 は、何も言っていないに等しいとしか読めない。
のはそのとおりで、実際に質問の答えになっていない。
空白が無いかどうかではなく何でぶった切られないかと言うのが質問。
だから「,」の外側はシェルが解釈出来る内容であれば良いが、
空白があればシェルによって別の引数として扱われるのは別の問題だし、
要するに
awk 'N''R == '`expr 1 + 1`' { pr''in''t'' }' file
がちゃんと動くことの説明としては、不足がある。
空白がないから「1つの引数」になってと説明されて、わからない奴が知能障害。ww
>>658 空白が有っても動く例
echo 'wa' `echo r\`echo o\`` 'ta'
cシェルじゃ動かないが
>>659 それ、3つの引数に分断されるよ。echoだから結局問題にならないだけで、
awkだと動かない。
>>657 > awk 'N''R == '`expr 1 + 1`' { pr''in''t'' }' file
↑は、awkのプログラム部分には空白がないじゃん。
だから「1つの引数になる」という説明(
>>645 )のとおり。
`expr...`の部分はバッククォートだから、
「クォートされていない空白」はない。
>>646 は、要約すると、「シングルクォートがシェルによって除去されること」
だけしか言ってなくて、それは当たり前だし、それだと、
途中のシングルクォートのところで「なぜ引数が分断しないのか」の
説明になっていない。
本質問者と思われる、
>>651 さんが、
>>648 の解答を「なるほど」と言っているので、
質問したかったことは「引数がなぜ1つになるのか」と言うことであることは明らか。
結論: 早期解答の
>>645 が正解。
>>661 >>質問したかったことは「引数がなぜ1つになるのか」と言うことであることは明らか。
君はエスパーか?
もし仮にそう言う意図で質問していたとしたら
>>644 では言葉が足りなさすぎる。
>>659 のようなものに対しても当てはまる質問と読むのが妥当。
従って、
>>645 は何の説明にもなっていない。
まあ、エスパー相手じゃこっちに勝ち目は無いが。
>>662 ×
>>645 は何の説明にもなっていない
○
>>662 の頭脳では、せっかくの
>>645 の説明が理解できない。
エスパーしなくても、
もう一度
>>648 の書き込みを見てみろ。
複数のクォート同士を、「空白」を入れた場合と入れない場合で説明してるだろ。
それに対して、質問者が「なるほど」と言って理解したんだから。
ポイントは、シェルの単語分割(引数分割)の際の「空白」について。
エスパーだろ。
>>644 と
>>651 が、同一人物だと見抜けてるし。
>>644 の質問から「引数がなぜ1つになるのか」という意図を見抜いたし。
常人には真似のできないことをするからエスパー。
ちなみに
>>648 を何度読んでも
「それはそうですが、何か?」
と言う感想しか抱けない。
>>664 なんだ、
>>664 は
>>648 が的を得た解答であることすら理解できてなかったのかw
awkにおいては、awkプログラムを、シェルから見て第1引数(argv[1])に与えることが
重要。
シェルスクリプトの中からawkを呼ぶ場合、awkプログラムの文字列が
シェルに解釈されるのを防ぐため、通常、全体をシングルクォートで囲むが、
そのシングルクォートの中の一部だけ、シェル変数で置き換えたい場合がある。
そんな時は、awkプログラムの途中で一旦シングルクォートを閉じて終了する。
(これが、
>>644 が言う「ぶった切れる」)
その直後に、「空白を入れずに」ダブルクォート付きでシェル変数を記述する。
その直後、再び「空白を入れずに」シングルクォートでawkプログラムの続きを書く。
この、複数のシングルクォートやダブルクォート同士の間に空白を入れないこと、
空白を入れるとシェル上で別の引数に分断されること、
awkでは「1つの引数としてプログラムを書く」必要があること、
と言うのが問題の本質。
>>645 はその答を簡潔に先に言っている。
また粘着合戦か 妹が泣いてるぞ
あほらし
>>644 は明らかにシェル変数もクォートされていると誤解した書き方だろう。
さらに一個目の「,」と二個目の「,」の間だけがコマンドに渡るはずと言う誤解。
その部分に対して一切
>>645 は示唆を与えていない。
別にawkだって適正に記述して複数引数として処理出来るようにすれば
クォートの外に意図的に空白を入れることも可能だ。
引数の数云々なんて、
>>644 からは一切読み取れない。
>>657 =
>>667 よ、興奮してるからと言って
シングルクォートとカンマを間違えるな。しかも3回も。
アンタ、もしかしてawkプログラムが複数の引数に分かれて渡されても、
awk側で(例えば BEGIN { と } の対応とかで)適切に連結されて
うまく処理されると誤解してたんじゃない?
だから、
>>649 で、
「スペースの有る無しは変数名が変わると言うことだし」
みたいなトンチンカンなことを言ったんでしょ。
>>668 typo位スルーしろ。
そもそも、そんなこと考えようともしないだろ普通。
第一
>>645 が何も言っていないと言うのと無関係。
そんな変態的な事を考えていたら、
>>645 が間違いだと突っ込むだろう。
スペースの有る無しは単に変数の内部、つまり$の後ろと勘違いしただけだろう。
で?
670 :
名無しさん@お腹いっぱい。 :2009/01/14(水) 15:23:54
>>667 >
>>644 は明らかにシェル変数もクォートされていると誤解した書き方だろう。
君はエスパーか? www
>>669 >スペースの有る無しは単に変数の内部、つまり$の後ろと勘違いしただけ
ふつー、そんな勘違いあり得ないよ。
そういう勘違いが起きること自体、
この問題の場合は「空白の有無」が重要、ということに
>>669 が気づいていなかった証拠。
だから
>>645 を見ても、その意味が
>>669 にはわからなかったのだろう。
>>645 は、
「シングルクォートは終了(ぶった切れ)しても、シェルの引数としては続いている」
と言うことを言ってるんだよ。それが的確な答え。
てか、
>>665 そんなこと書いて知らない人が鵜呑みにしたらどうするんだ?
0と1は、まあtypoと大目に見ても、
オプションとか全く考慮していないのはどうか?
そろそろサマリをくれ。
>>672 typeじゃないよ。argv[1] で合ってる。
argv[0] は awk の文字列。
>>670 >>正規表現中の「'」
内部に無い以上前後を一括りにしてしまっていると読むのは妥当。
>>671 だから
>>644 の質問に「空白の有無」なんて重要じゃないと何度言ったら・・
分からなくて当然で、明後日の回答内容なんて気にするわけないだろ。
斜め読みにきまってる。
>>シェルの引数としては続いている
こう言う常人には見えない文字が見えるのがエスパー
>>673 >>665 がサマリとしてもよくまとまってると思う。
>>674 の言うとおり、typoじゃないね。
(674自身はtypeがtypoだがw)
>>674 誰が、処理内容がargv[0]だと言った?
自分で第一引数って書いただろ。
まあ第一と第二のtypoということにしておいてもいいが、
そんなことより根本的におかしいだろ「重要」だなんて。
>>676 そりゃ最悪だ。
嘘を重要といい、
明後日の事をくどくど書いて「問題の本質」だと?
>>677 だからtypoじゃないって。
awk = argv[0] = 第0引数
awkプログラム = argv[1] = 第1引数
awkプログラム部分を「1つの引数にする」「2つ以上に引数に分けてはいけない」
ことは重要。
確かに、-F とか、その他awkのオプション引数が入る場合は
awkプログラム部分は argv[1]より後ろにずれるが、
そういうことを言ってるんじゃない。
>>765 自分が理解できないということすなわち自分が無能であることを、
力説しているキミには同情を禁じ得ない。ww
>>675 自分が理解できないということすなわち自分が無能であることを、
力説しているキミには同情を禁じ得ない。ww
すごいな 苦し紛れに漢数字をアラビア数字に書き換えか。
>>675 理解できないんじゃなく価値が低いと看做したから
斜め読みしたと書いたつもりだが?
で、変数のところに空白がはいりゃそりゃ意味が変わるから
動かなくて当然だと早とちりしただけであり、
>>645 が
>>644 に対して何も言っていないと言う主張と全く矛盾しない
というか、極めて整合性が有る。
>動かなくて当然だと早とちりしただけであり、
www
なんだ、
>>646 の解答はやっぱり「早とちり」だったのか。
それがすべてだな。
まあ良い。 シェルから見て第0引数という表現は 実に気持ち悪いが、まあ無いわけではないから許してやる。 しかしオプションを無視した上に、 別に何の変哲もないことを力説して、 重要だの本質だのというのは頂けない。 しかもawk特有の様に語るところがミスリードを意図しているようで気持ち悪い。 空白をセパレータとして認識するのはシェルだし、 パラメータを複数受け取っても、 それがコマンドにとって適正であれば動くし、 不適であれば動かないという一般的な話なだけであって、 敢えてawkを例に出して力説するような物じゃあ無い。
>>686 >敢えてawkを例に出して力説するような物じゃあ無い。
あのー、もともとシェルスクリプト(#!/bin/sh)の中から
awkを呼び出す場合の話なんですけどー
敢えてawkを例に出したんじゃなく、
元々がawkを呼ぶ場合の質問。
その場合には「引数を1つにまとめる」ことが重要。
>>686 >しかしオプションを無視した上に、
awkをワンライナー的に使う場合(シェルスクリプトの中のワンライナーも含む)は、
awkに各種オプションを付けることがあるが、
複数行に渡るawkプログラムを記述する場合は、
混乱を避け、書式を統一するためにも
awkのオプションは付けない方が言いよ。
例えば、-fオプションなら、プログラム中でawk変数のFSでセットできるわけだし、
FSの方を使った方が言い。
そういう意味で、awkのプログラムは argv[1]の位置に来る。
>>689 typo発見。
× -fオプションなら、プログラム中でawk変数のFSでセットできる
○ -Fオプションなら、プログラム中でawk変数のFSでセットできる
でも言ってることは合ってるよ。
>>688 #!/bin/sh
A=file1
B=fil2
awk '{
print
}' ''"$A"'' "$B"''
状況次第で引数を分断する事も重要。
>>691 アフォか。
それ、「awkプログラム部分」はどこも分断されてないだろ。
awk自身の引数のファイル名のところの話じゃないんだよ。
主張しているのは「awkプログラム部分を分断せずにひとつの引数にまとめること」
要するに、
>>600 が、
書いた本人は勿論そう言うつもりは無いだろうが、
後半の文章だけを取り出すと大間違いなのに
>>665 のようなスタンスだと、そのことに気づきにくいのが
問題なんだよ。
動くような引数を渡せば、echoもawkも動くし
そうでなければ、どれも動かない。
単純に引数を一つにまとめるのが重要と
決め打ちするのは良くない。
しょうもないののしりあいしてるとこに双方タイプミスとかするなよ ↓ 以下、タイプミスした方が論旨関係なく即刻負けね
>>693 awkで、「awkプログラム部分」を、2つ以上の引数に分けて動くような例は
ありえない。
だから、「awkプログラム部分は1つの引数にする」と
決め打ちして何も間違いはないし、より論旨がはっきりする。
>>692 君がそう言いたい事は分かっている。
しかし、君の書き方だと知らない人は確実に誤解する。
そう言う意味で、
>>644 が「シングルクォートの後ろで空白が入るとどうなるんですか?」
というような質問でもないのに、
>>645 を書いたのが
何の説明にもなっていなく、誤解の元だというのが私の唯一の主張。
誤解誤解って、どう誤解するの?確実にっていっても想像でしょ?
>>646 は、まだ見苦しく言い訳続けてるの? とことんがんばれ。www
>>645 がすべてだからねえ。
それを理解できない馬鹿が己の馬鹿っぷりを力説しているだけ。
>>700 別に知識レベルを争っている訳じゃないだろ。
まあ君のような高尚な知識は、現実世界には不要だろうがね。
>>701 まだ言ってるよ。
馬鹿じゃねーの。
的外れと言う指摘を脳内変換して
間違いだと言われたと勘違いして
相手の論を勝手にでっち上げ、攻撃する屑よ。
>>703 良かったね。
君のところではまともに動く物が、
ウチでは理解出来ないで、空白が混入して動かない訳だ。
君のところが儲かって結構な事じゃないか。
そう解釈してくれるなら、実際ウチも嬉しいから、
がんがれ。
>>645 は何の実例も提示せず、後付の言い訳に終始する。
>>646 は、豊富な実例を実際に表記している。
この一事をもってして、軍配がどちらに上がるか
自明の事であろう。
>>690 の自演も見苦しい。
そもそも重要なのは
>>689 の言う
-f オプションは、関数などをライブラリ化したファイルを読むのに
必須であり、決してシェルスクリプト中にオプションを記述するのが
忌避されている訳ではない証左ということ。
ちなみに-vオプションだって頻繁に使う。
-Fだってケースバイケースなのに無理やり自己の論に
押し込めようとするから破綻する。
とにかく、自分の枠で決めつけるのはよせ。
>>705 お前ほんとに
>>646 本人か?
>>646 の発言として
>>697 より引用するが、
>
>>644 が「シングルクォートの後ろで空白が入るとどうなるんですか?」
> というような質問でもないのに、
>>645 を書いたのが
> 何の説明にもなっていなく、誤解の元だというのが私の唯一の主張。
「唯一の主張」って言ってるね。
つまり、
>>646 は、
>>644 の解答は的はずれだったことは暗に認めているわけだ。
そして、残った「唯一の主張」として、
>>645 の解答でも「誤解の元だ」
と言ってるに過ぎない。
実際には誤解の元とは思わないが、少なくとも
>>645 の解答で正解なのは事実。
よって、軍配はすでに
>>645 に上がっていることを
>>646 も認めている。
同じような書き込みを何回もするなよ
>>707 それは awkプログラム文字列が argv[1]の位置に来ることが多いから
わかりやすくそう言っているだけで、
論点は「ひとつの引数にプログラムをまとめる」ことだから、
今の議論と関係ない -v とか-F オプションを持ち出すのは論点をぼかすだけだよ。
だからあえてオプションのことは言わずに argv[1]と言っただけのことと思われる。
>>707 どうでもいいが、ワンライナーでもないのに awk の -v オプションを使うのは
非常にお勧めしない。
きちんと BEGIN { } の中で変数に代入すること。
あと、-f は #!/usr/bin/awk -f なスクリプトの場合に使うべきもので、
シェルスクリプト中にawkプログラムを各場合は、-f オプションとは両立しない。
(-f を付けたら引数からはプログラムを読まなくなるので)
>>712 パラドックスを書くな。
-f も、-v も何度でも使える。
>>713 「何度でも使える」かどうかを言ってるんじゃないよ。
じゃあ聞くが、
awk -f prog-file
って書く場合に、どうやってawkの引数にプログラムを記述するんだ?
別ファイルじゃなくて、引数に直接プログラムを記述したい場合、
-fオプションは使えないだろw
その場合、普通に書けば委員ジャマイカ? この一時を以ってしても、 第○引数がどうでも良いことがわかるね。
>>715 試してから書け。
awk -f prog 'BEGIN { ... }'
なんて書いても動かないぞ。
awk -f progfile
と
awk progstring
とは
エクスクルーシブ。
同時に使えない。
1000まで続けるつもりですね。
>>718 だから、
>>715 が「書ける」って言ってるから「書けない」と反論してるんだよ。
>>715 は、
awk -f prog-file
と
awk prog-string
を両立した例を示すこと。(不可能だけど)
言っとくけど、
awk -f prog1 -f prog2
じゃ駄目だよ。
あくまで「引数に直接」awkのプログラムを書くこと。
じゃ、セカンドステージは、
>>714 =
>>715 =
>>716 「awkの -f オプションと、引数直接プログラム記述は両立しない」
と言う主張と、
>>713 =
>>715 =
>>718 「awkの -f オプションと、引数直接プログラム記述は、『普通に書ける』」
と言う主張と言うことで。
セカンドステージは誤字即退場ということで。
気持ち悪いな。 頼むからおまえら「シェルスクリプトを書いてます」 なんて、公言しないでくれな。 俺まで同類だと思われると困るから。
特定ディレクトリに無数のスクリプトがあるんですが、 これらはある親シェルを起動すると実行されます。 ただ、子シェルでなくて、孫、曾孫シェルの可能性もあります。 この特定ディレクトリにあるスクリプトのうちどれが実際に起動されたかを調べる方法ないでしょうか? すべてに起動ログをはかせるのはちょっと厳しいです。
A. BSD accountingがあれば、lastcommで終了。 B. /bin/shに読まれて、access timeが変るので、ls -ltu してタイムスタンプ確認。 C. ptrace系のコマンド使う D. /etc/profileでログを取る
>>718 もしかして、
>>718 の言う「普通に書けば」って、
「普通に -f を使わずに書けば」って意味じゃないの?
でもそれだと、
「シェルスクリプト中から、awkプログラムを直接引数に書いてawkを呼び出す場合、
-fオプションは使わない(使えない)」
という、
>>716 =
>>714 の主張を認めたことになる。
よって、セカンドステージは
>>716 =
>>714 =
>>719 の勝ちということで終了。
>>726 は朝6時にレスなんてよほど悔しかったの?乙
シェルスクリプトスレなんでawkのオプションとかスレ違いなのにこんな話題しかないのかな
>>713 =
>>715 よ、
-f を何度使ってもいいから、
awk -f プログラムファイル 'プログラム文字列'
が両立できる方法を示せ。
君はそれが「普通に書ける」って言ったんだぞ。
間違いを広めると迷惑だから、
書けないなら「書けない」と訂正したらどうだ。
なんか自分がみっともないと思わんか?
>>707 は勘違いしてるようだね。
> -f オプションは、関数などをライブラリ化したファイルを読むのに
> 必須であり、
↑って言ってるが、
この発言から、-f オプションで別ファイルに入った関数ライブラリを
読み込んだ上で、さらに awk引数でプログラムを書けると誤解しているようだ。
awk -f 関数ライブラリファイル
って記述したら、
awk引数にプログラムは書けない。
敢えて書くなら、
awk -f 関数ライブラリファイル -f プログラム本体ファイル
ってやるしかない。これではプログラム本体が別ファイルになるから
シェルスクリプトでこんなことはしない。
ようやくセカンドステージが盛り上がってまいりました。
と言うかさぁ、元祖大元の
>>639 が書いた awkスクリプトが、
-f も -v も -F も使ってなくて、
argv[1] にプログラムを直接記述する方式だろ。
これが元になって始まった議論だから、
>>665 が、
「awkプログラムを、シェルから見て第1引数(argv[1])に与えることが重要」
って言ったんだよ。
argv[1]の[1]の数字はあまり重要じゃなくて、
argv[2]以降の別引数に分割せずに、ひとつのargv[*]だけにまとめること、
というところが主眼ね。
それを、
>>639 にありもしない -f や -v や -Fオプションの話を勝手に持ち出して
>>672 が論旨と違うところに突っ込みを入れたのが間違い。
おそらく、話の流れを全然読んでなくて、途中から一部だけ読んで
突っ込んじゃったんだろうな。
a='cat a.dat' b='cat b.dat' c='cat c.dat' 改行を*nで表現すれば sedだけでしょ? awk使いはきもいよ
ラ…ラ…ア……ファ……
>>725 ありがとございます
この中だとaccess timeで確認がいけそうなんで使わせてもらいます
サードステージを始めさせようという釣りだと思う。
シェルスクリプトで現在のユーザーでシェルを起動したときのプロンプトを取得したい のだけど、どのようにすれば可能でしょうか? bash限定でも構いません。
「シェルを起動したときのプロンプト」ってどういう意味だよ。 localhost% bash の「localhost%」がほしいのか? ログインシェルなら、そもそも起動したときのプロンプトなんて存在しないし。
>>740 bashが起動して、PS1が展開された結果です。
echo exit | bash -i の結果を加工するとか
promptがstderrに出力されるようだけど、 stderrをリダイレクトするとJob Controlできないというメッセージがでてじゃまくさい。 bash: no job control in this shell [user@host ~]$ exit
bashはインストールしてないから試してないが、環境変数EMACS=tで抑制できるかも。
warningが必ず出力されるのが確かなら。 PROMPT=`echo exit | bash -i 2>&1 | sed -e 1d -e s/exit$//`
746 :
名無しさん@お腹いっぱい。 :2009/01/16(金) 15:00:40
zshだと、 $ echo exit | zsh -i すると、zshのプロンプトを出したままになり、exitしてくれない。
a="this" b="is a pen" というふたつの変数があったとします。これらを結合してoptsに代入して command ${opts} としたときに、[this] [is a pen] というふたつの引数が渡された、と解釈させるようにしたいのですが どういう風に連結すればいいんでしょうか。 opts="${a} ${b}" だと [this] [is] [a] [pen]、 opts="\"${a}\" \"${b}\"" だと ["this"] ["is] [a] [pen"] という風に解釈されてしまします。
pshってどんなもんなの もしもperl shellにしておくとperlの起動コストが無くなるとか言うならば 使いたい所だけれど
>>748 $ a="this"
$ b="is a pen"
$ set "$a" "$b"
$ python -c 'import sys; print sys.argv[1]; print sys.argv[2];' "$@"
this
is a pen
$
751 :
748 :2009/01/17(土) 00:30:47
>>750 変数に代入したいんですが、それはできないんでしょうか。
いろんな条件によって順にオプションを追加していく・・って感じのことがしたいんですが。
>>751 パラメタにスペースが入らないルールにするのがベスト
それが出来ない場合、かつ、パラメタにダブルクォートが入らない
としてよければ、
>>748 にあるようにダブルクォートで括るのも
手かもしれない。その場合、eval するのが簡単でよいかと。
a="this"
b="is a pen"
opts=\"$a\" \"$b\""
eval command $opts
タイプミス opts="\"$a\" \"$b\""
754 :
748 :2009/01/17(土) 01:26:49
>>752 オプションにはファイルパスが含まれるので、スペースやダブルクオートがないと仮定するのは
ちょっと厳しいです。
うーむ・・・
やっぱり set が一番現実的だろう。 set -- set -- "$@" "$a" set -- "$@" "$b" って感じで。
>>748 要するに、"$@" と同様のことを、一般のシェル変数でやりたいんだろ。
bash限定なら配列使っちゃえ。スペースもダブルクォートもOKだよ。
opts[1]="This"
opts[2]="is a pen"
command "${opts[@]}"
>>755 純正シェルでは、set -- では引数が削除されないので注意。
必ず、
set dummy; shift
ってやること。
758 :
748 :2009/01/17(土) 11:16:27
>>756 おお、これでできました。どうもありがとうございます。
bash依存ぽいですが、それくらいは仕方ないかと
759 :
748 :2009/01/17(土) 11:58:00
ぽいというか、そうおっしゃってましたね。 失礼しました。
だから、evalで良いのに。 なんで運動靴履くの?
761 :
名無しさん@お腹いっぱい。 :2009/01/18(日) 00:45:06
シェルを使い始めたばかりの初心者です。 gccのプログラムがエラーを返すまで自動で何度も実行するシェルを書きたいのですが上手くいきません。 下記のような書き方でやってみました。 gccのプログラムはリターン値が-1のときにエラーと仮定しています。 while [ gccのプログラム = 0 ] do … done レベルの低い質問で申し訳ないのですが、よろしくお願い致します。
シェルってゆうな。クズ。
>>761 while true; do command && break; done
>>761 while command; do
:
done
ただこれだと
>>763 と同じで、exit値0以外がエラー。
while ture: do
command
if [ $? = -1 ]; then
break
fi
done
これで-1の時だけエラーと見做す。
プログラムの終了コードが -1 ってのは良くない。 もしそうなら、 while [ gccのプログラム = 255 ] ; do hogehoge とすればよいと思う。でも終了コードを1とかの正数に変えたほうがいいよ
ああ、なんか読み落としていた。
>>761 がつまづいたのは、$? を使ってないことなのか。
でも
>>764 の $? の比較は、255と比較すべきじゃないの?
>>761 文字列の比較じゃないのに test [ ] を使ってるのが間違い。
while gccのプログラム
do
...
done
でよい。
whileはもともと終了コードをチェックする文法。
通常、testコマンドである [ ] と組み合わされるが、
この場合は gccの終了コードを直接チェックするから、[ ] を書いてはいけない。
(ほかに、$?を使う方法もあるが、while gcc ... って書けば $? も使わなくていい)
>>761 すげー、回答者全滅。
>>763-
>>767 すべて間違い。
以下が正解。
until gccのプログラム
do
...
done
whileとは終了判定が逆の until文を使う。
エラーを返すまでだからwhileでいいんじゃねーの?
てか、 while [ command -ne -1 ] do ... done だろ。
while gcc ... [ $? -ne 255 ] do ... done だろ。
773 :
771 :2009/01/18(日) 12:27:13
>>772 実験したら、
>>771 では駄目だと判明。
もちろん
>>763-764 も駄目。
>>765-767 あたりも参考にすべき。
どうもtestは数値を1バイトの符号なし整数とみなすようだ。
これはunixコマンドの終了ステータスが0-255の範囲であると
定められていることと関係するのだろう。
smpl.c
#include<stdlib.h>
int
main(int argc, char *argv[])
{
int i = atoi( argv[1]);
return (i);
}
jikken.sh
#!/bin/sh
set -x
i=1
while true; do
./a.out $i
if [ $? -ne 255 ]; then
echo "OK"
else
echo "error" && break
fi
i=`expr $i - 1`
done
774 :
771 :2009/01/18(日) 12:32:57
すまん、testの仕様じゃなくて、 終了ステータスを出す側が符号なし整数でだしてた、 いずれにしても。 実行結果 + i=1 + true + ./a.out 1 + [ 1 -ne 255 ] + echo OK OK + expr 1 - 1 + i=0 + true + ./a.out 0 + [ 0 -ne 255 ] + echo OK OK + expr 0 - 1 + i=-1 + true + ./a.out -1 + [ 255 -ne 255 ] + echo error error + break
最凶の釣り師だな。 「gccのプログラム」、「リターン値が-1のときにエラー」、「シェルを書きたい」
>>777 終了ステータスが0-255まで有ると言うことは、
非ゼロで有っても何らかの理由でその数値を利用するため。
ゼロ以外は何らかのエラーで有るという考え方はOKだが、
何でもかんでも処理を中断して良い訳じゃない。
そこは、プログラムの仕様で判断するべきだし、
今回の仕様は
>>761
>>788 だったら、以下のとおり。
これくらい応用して考えろよw
↓
while gccのプログラム; [ $? != 255 ]
do
...
done
>>779 終了ステータス判定に文字列比較演算子を使うな。
要するに、
>>761 への回答は、
「gccプログラムの終了ステータスは-1には出来ません」
gdb で return(-1); なプログラムを動かしたら、
Program exited with code 0377.
だと。
>>778 いや、今回の質問は、そもそもエラーコードの受け取り方を
>>761 が勘違いしていたのが原因なのだから、
その原因に対する的確な答えは、
>>767 が正解。
>>761 で、「リターン値が-1のときにエラー」とは言っているが、
これはその「gccのプログラム」が 「return -1;」と記述されていることを
言っているに過ぎず、質問のポイントとなっているのはエラーコードの値ではない。
実際、-1 とか 255とか、数値の問題でうまく動かなかったのじゃなく、
while [ gccのプログラム = 0 ] みたいな間違った書き方をして動かなかったのだから、
それに対する指摘が正しい回答と言えよう。
その意味でも
>>767 が正解。
エラーコード=255を杓子定規に解釈すれば
>>779 だが、
これが本当に意図していた回答かどうかは疑問。
>>782 深読みじゃないよ。質問で [ gccのプログラム = 0 ] って書いてるんだから、
エラーコードが 0 かどうかチェックしたいと言う意図だろ。
それが質問の「仕様」。
どうでもいい。 黙れ。
仮に、正常終了時に標準出力に0を出すのだとしても、書くなら while [ `gccのプログラム` = 0 ] だよな。
どうでもいい。 黙れ。
>>780 $?を参照する方法なら文字列比較で構わないよ。
変数の値は文字列だから
>>788 だな。
>>780 -eq -ne 等を使う必要があるのは、たとえば、
3 03 003 0003 ... などを同一の値とみなす必要がある時。
[ 003 -eq 3 ] && echo 同じ
とか。
$? の場合は、0〜255の普通の値しか入らない(00とか000とかにはならない)から、
[ $? != 0 ] で判定して良い。
>>788 無様なコードでも動けばそれでいいというわけだ。
>>781 プログラム終了コードを -1 にしたことが
問題だったのなら、的確な答えは、
>>766 +
>>764 が正解
>>767 ではプログラムの終了コードが0か否かしか
判定できない手法なので、残念ながら完全に間違い。
>>761 の要求は満たしてない。
終了コードが3種類以上ある場合、 case $? in 0) hoge;; 1) hoge;; 255) hoge;; *) hoge;; esac みたいに書くこともある。 case文は文字列としての比較しかできない。 「$?を文字列として扱ってはいけない」というルールなら、 caseで効率良く書くことも否定することになる。 ↓ それは明らかにおかしい。
というか、ちょっと前から沸いてる
>>781 って
多分
>>767 と同一人物だと思うんだけど
なんか自分の答えが正解と言い張って、他人の答えを間違いと
断言する性癖があるね
もう少し余裕もった方がいいと思うよ
>>791 違う。
質問者が本当に「エラーコードが-1かどうか」を判断したかったのなら、
質問でも、(間違った文法だけど)
while [ gccのプログラム != -1 ]
と書いていたはず。
実際には
while [ gccのプログラム = 0 ]
と書いて質問したのだから、
質問の「仕様」は、エラーコード0かどうかで判断するということで正解。
>>794 そもそも、(もし釣り質問で無いなら)
質問者が、どうしていいか訳が分からなくなってる質問内容の
一分だけが、正確に質問者の意図を反映しているというのは強弁。
揚げ足取りするつもり無いけど自分が正しいと主張する人は
>>764 × ture: 綴りも違うし、区切りがコロンになってる
○ true;
>>779 × while gccのプログラム; [ $? != 255 ] 条件部分は1つのコマンド/パイプライン(相当)しか書けない
○ while ( gccのプログラム; [ $? != 255 ] )
雑はやめてくれ
798 :
797 :2009/01/18(日) 18:35:48
変な形で繋がったけど × 条件部分は〜 ○ while の条件部分は〜
雑はやめてくれ
>>797 嘘を書いてるのはお前。
whileの条件部分に書けるのは「パイプライン」じゃなくて「リスト」
リストというのは複数のパイプライン。
while gccのプログラム; [ $? != 255 ]
↑は正しい。
× while ( gccのプログラム; [ $? != 255 ] )
↑
サブシェルが無駄。
おれも
>>800 が正しい、に1俵。
whileの条件部分には、( ) なしで2個以上のコマンドが書ける。
>>797 試しに、↓みたいなの実行してみろ。
i=1; while echo $i; i=`expr $i + 1`; [ $i -le 10 ]; do :; done
>>799 失礼雑だった
>>800 リストまではOK
> while gccのプログラム; [ $? != 255 ]
>↑は正しい。
は?
>>802 おまえ、「リスト」知らんのか。
コマンド; コマンド;
みたいにセミコロンで区切ったのがリスト。(改行でもいいが)
リストが桶ということは、2個以上のコマンドが桶。
while gccのプログラム; [ $? != 255 ]
の代わりに、
while echo hoge; [ $? != 255 ]
とでもやってテストしてみろ。ちゃんと動くから。
あと、
>>801 が書いてくれたテストプログラムも、
while の条件文に複数のコマンドを書いた例だな。
たぶん、あれだろ。
>>802 は。「リスト」が、&& や || を使ったのしか駄目だと
勘違いしてるんじゃないかww
セミコロンでも改行でもOK。
自演しておきながら、 よくまあ他人同士のふりができるな。 タイミングと言い、やりとりといい、 よくまあ毎回毎回同じパターンで 飽きないか?
>>802 > リストまではOK
リストまではOKってことは、
>>797 の主張が間違ってたってことだよ。
hoge && hage && boke
hoge || hage || boke
hoge; hage; boke
上の3つは全部「リスト」。
ちなみに、
hoge
hage
boke
みたいに3行に書いても全体で1個の「リスト」。
while
hoge
hage
boke
[ $x -ne 0 ]
do
.....
done
みたいな変わった書き方もある。
オナニーは人から見えないところでやれ。 ああ、見られないと出来ないのか。
>>806 普通、人の間違いは指摘する事は有っても、
わざわざ、釈明せよ等とは言わないものだ。
お前、もう良いから、このスレから出て行ってくれ。
邪魔だ。
shのオプションで何が一般的ですか -fはよく見るけど何もないのもよくみるけど
-f は csh じゃないの?
>>797 恥晒しとくね
>whileの条件部分は1つのコマンド/パイプライン(相当)しか書けない
>whileの条件部分は1つのコマンド/パイプライン(相当)しか書けない
>whileの条件部分は1つのコマンド/パイプライン(相当)しか書けない
>whileの条件部分は1つのコマンド/パイプライン(相当)しか書けない
>>809 「人の間違いを指摘した」のではなく、
「もともと正しかった人を『間違ってる』と指摘した」(
>>797 )のだから、
話が違うだろ。
>>813 お前がいつもやってることだろ。
誰か他の人間は釈明要求とかしたか?
早く消えろ。
お前がいるとシェルスクリプトその物の評価が下がる。
結果、クソOSが跋扈する。
あ・・さてはお前、windozeの回し者か?
このスレが荒れて流れりゃボーナス倍増か?
・・・ってそんな感じ。
いやはやしかし、whileにあんな書き方があるとは。 while hoge hage kasu [ $x -ne 0 ] do 頭固いからよくわからん、なにがどうなってるのやら。 ところで、logのこのメッセージって何。 loggerでログ取ったら紛れ込んでくるんだが。 daemon.infoカテゴリー last message repeated 2 times
816 :
761 :2009/01/19(月) 01:03:47
こんなに色々やり方があるとは思わず、大変勉強になりました。 皆さん色々なアドバイス、ありがとうございました。
htmlを拾ってきて、リンクのところだけ抽出したいと思ってるのですが、 とりあえず下のようにa hrefタグだけ抜こうとしてもうまくゆかないです。 なんででしょう? echo ' fadadf <a href="2xxxxxx"> fdskaf' | sed 's/\(<a href[^>]*>\)/\1/'
>>817 htmlの内容にもよるけど、
< a href="hoge">hoge<\a>< a href="hoge2">hoge2<\a>< a href="hoge3">hoge3<\a><br>
っていう感じだからそれじゃ全然だめ。
例題はこれでいけたけど?
echo ' fadadf <a href="2xxxxxx"> fdskaf' | sed -E 's/.*(<a href[^>]*>).*/\1/'
大雑把でいいんならこんな感じ。 strings hoge.html | fold -s -w 60 | grep "href" よくfetchでエロを(ry
>>818 ありがとうございます
そういえばマッチするとこの前後を考えてませんでした。
一応対象のファイルは1行につき<a href>タグ一個なのでうまくいきそうです
>>819 これは初めて知りましたがうまくつかうと楽そうですね
821 :
初心者です :2009/01/19(月) 18:53:31
初心者ですが、スレ違いだったらすみません。 教えてください。 最近10日以内に変更したファイルやディレクトリ(新規作成ファイルを含む)を検索して、ディレクトリとファイル名の詳細(ls -ltrのような感じ)を変更時刻でソートして画面出力したいのですが、どなたかご教授お願いします。 ちなみに、IBMのAIXを使っています。
>>821 変更時刻でソートをちゃんとやるのは難しい。
find / -mtime -10 -ls
あたりで我慢して。
>>821 AIXは知らんが、-print0が使えるfindがあるなら、
↓
find / -mtime -10 -print0 | xargs -0 ls -ldtr
なければGNU find入れれば使える。
xargsを使うな!
>>821 find . -mtime -10 -exec ls -ldtr {} +
コマンドラインの最後、「+」 なので注意してね。
GNUのlsなら--time-styleで時刻の表示形式を決められるので ソートしやすい形式にすれば楽だと思うよ。
>>823 ,824
それだとファイルが多いときにlsが複数回起動されて、lsによる
ソートが起動毎になっちゃうからだめなんじゃない?
なんで、問題ないってわかるんだよ。制限値は意外と小さいぞ。
829 :
初心者です :2009/01/19(月) 19:49:11
822〜828の方々へ 早速のレスありがとうございます。 本当に助かりますし、心強く思います。 ただ、私はただいま会社にいませんので、すぐにでも試したいのですが試せないんです。 明日会社で必ず試してみます!
1回のlsにおさまらなかったらこんな感じでいけると思う find . -mtime -10 -exec ls -ld --time-style=full-iso {} + | sort -k 6,7 日付の表示形式が気に食わなければ+FORMATでdateコマンドと同様の フォーマット文字列が使えるので工夫してくれ。
GNUツール禁止
まあ、あれだ。AIXだから GNUコマンド群は使えないというのがネックになるだろう
find で -ls した結果を保存。 分単位でソート。 同じ分のファイルごとにグループに分けてls -ltrdでソート。 (グループ内にはそれほど多量にないと仮定) 連結。 コードは誰かまかせた。
834 :
初心者です :2009/01/19(月) 20:41:25
たびたび、初心者です。 みなさん、レスありがとうございます。 「変更時刻でソートして画面出力」と書きましたが、誤解があってはいけませんので、目的を書きますが、 ファイルの新しいものが一番下にくるように画面出力したいのです。 正しくは、変更時刻とは分単位ではなく、タイムスタンプの順番です。 ですから、できることなら100分の1秒でも新しいファイルが下に来てほしいです。 この目的だと、どんな記述がよろしいでしょうか?
(1) find で -ls した結果を保存。 (2) argsがオーバーフローしないように、 上から1000ファイルずつ区切ってそれぞれをls -ltrdでソート。 (3) 次に、上から500ファイルを飛ばして、 その次から1000ファイルずつ区切ってそれぞれをls -ltrdでソート。 (4) 今の状態を一時保存し、(2)と(3)をもう一度繰り返す。 その結果が一時保存した結果と変わっていれば、再度(2)から繰り返す。 変化がなくなればソート完了なので、これで終了。 コードは誰かまかせた。
>>834 ファイルの持っているタイムスタンプは秒単位だから
1/100秒とかは無理
・・・AIXのFSは知らないけど
GNU lsがないと秒単位のタイムスタンプも取得できないんだよなぁ
通常ファイルだけならdiff -cでも取得できるでしょ。 ディレクトリはわからんなぁ。
diff -c の裏技でタイムスタンプ取得できるのは 通常ファイルの中でも、テキストファイルだけ。 バイナリファイルだと diffに拒否される。
こっちでは diff -ac でできるけど、OS依存?
>>840 diff の -a は GNU 依存だろ。
tr とかで半角カナを消したいんですけどどうすればいいでしょう?
んじゃ別解 mkdir ../temp find . -mtime -10 -exec ln {} "../temp/`echo '{}'| tr / :`" \; ls -t ../temp | tr : /
>>821 >>834 適当な一時ディレクトリを作り、
その一時ディレクトリに find の結果出て来たファイルをすべて ln -s する。
その一時ディレクトリ上で、
ls -lLdtr を実行して結果を画面に表示。
一時ディレクトリをシンボリックリンクごと削除。
コードは誰かまかせた。
勝ったな。完璧に勝った。
お題の「ファイル」という条件が抜けてたな。
>>844 は、別ファイルシステムが含まれてると対応できないし、
ディレクトリ自体のタイムスタンプがチェックできないし、
ファイル名に : が含まれていると破綻する。
>>845 でいいじゃん。
>>845 も
>>844 も、
異なるディレクトリに同名のファイルがあったら破綻するのでは?
/hoge/file と /boke/file とか。
>>844 はそれを:で逃げようとしてるわけで(不完全だけど)、
>>845 でうまくエスケープするコードも必要。
みんな色々言ってるけど、実際に自分が必要となったら PerlとかRubyとか使うんじゃないの? find path -mtime -10 -print | perl -e 'chomp( @all = <> ); print join "\n", sort { -M $b <=> -M $a } @all;'
自分なら GNU ls (coreutils)を入れて --time-style= で出力して sort一発にするなぁ。
そういうのを入れないでこのお題を解くという空気が流れているんだが
>>854 >>853 は
>>852 に答えたんだが、、
お題を解くのとは別に、実際に自分が必要になった場合の話。
お題の解は実際には実用にならないので。
あれば使う。 無くてもやらなきゃならない場合がある。
無理に一つのやり方に決めることもないんで、いろんなやり方を考えて みる方が幅が広がっていいんじゃねー?
symbolic linkと-Lを組み合わせるやり方は目から鱗だったが、 先のファイルがsymbolic linkだったときは結果が違ってしまう のが惜しいね。
posixには-Lが無いからハードリンクにしたのだが。
AIXにはstat(1)はあるっけ?
stderrとstdoutを端末に出力しつつ、それぞれ分けてファイルに出力したいのだけど、可能でしょうか? command 2>> /tmp/stderr.log | tee -a /tmp/stdout.log こんな感じでやってみてるのですが、上記だと端末にstderrは出ません。
分けんのは無理だね。 別の端末でtail -f /tmp/stderr.logしなよ。
>>861 できるよ。
(command | tee -a stdout.log) 2>&1 > /dev/tty | tee -a stderr.log
>>862 無理じゃないよ。
zshなら素直にかけるんだけどね。 sh hoge.sh > >(tee stdout.log) 2> >(tee stderr.log)
>>863 さらに、commandのexit statusを得ることは出来ないでしょうか?
>>865 できるよ。
(((command; echo $? 1>&3) | tee -a stdout.log) 2>&1 > /dev/tty | tee -a stderr.log) 3>&1
>>866 それだと、exit statusが表示されてしまうだけだ。
ややこしくなるけど↓かな。
(((command; echo $? 1>&3) | tee -a stdout.log) 2>&1 > /dev/tty | tee -a stderr.log > /dev/tty) 3>&1 | (read s; exit $s)
868 :
初心者です :2009/01/20(火) 20:50:30
昨日質問させていただきました「821,829,834」です。 皆さん、本当にいろいろアドバイスいただき、ありがとうございました。 無事、できました!感激です! 特に、「824」さんの解答にあった通りにしたら、できました。 ありがとうございます。 ところで、もしこのレスを見ていたらで結構ですので、たびだび質問で恐縮ですが、 find . -mtime -10 -exec ls -ldtr {} + の最後の+記号の意味はなんでしょうか? 私がもっている本で調べたりしても、のっていなかったので、もしよかったら教えてください。 他の方々の例もいろいろと勉強になると思い、試してみたのですが、まだまだ、私の勉強不足で思い通りに動かなかったりしました。 どうやら私の会社のUNIXは、GNUツールが使えないようです。残念・・・ でも、みなさんのアドバイス、本当にうれしかったです。 ありがとうございました。 また、何かありましたらご教授ください。
869 :
827 :2009/01/20(火) 20:55:31
やっぱり「実用上問題ないからヨシ」じゃん
ある日emacsあたりを新規インストールあるいは更新して、 全部出てこないじゃないかーと怒られる
GNUが入れられないシステムらしいからemacsを入れるようなことはあり得ないだろ。
874 :
名無しさん@お腹いっぱい。 :2009/01/20(火) 23:53:05
質問です! OSのバージョンをuname -rで取得し、5.4-RELEASE-p6以上だったら、echo hogeを実行し、 5.4-RELEASE-p5以下だったら、echo fooを表示するシェルスクリプトを作りたいと思ってます。 しかし、5.4-RELEASE-p5のような形式の文字列を比較する方法がわかりませんが、どのように比較すればよいのでしょうか?
>>874 if [ `uname -r` = "5.4-RELEASE-p6" ]; then
echo "hoge"
fi
if [ `uname -r` = "5.4-RELEASE-p5" ]; then
echo "foo"
fi
>>874 testコマンドが対応していれば strcmp()による文字列比較も使えるので、
一応(p10とか2桁とかならない範囲なら)これで出来る
if [ `uname -r` \> "5.4-RELEASE-p5" ]
then
echo foo
fi
>>874 5.4-BETAはどうするの?
仕様をもうちょっときっちり書いて欲しい。
一桁.一桁-RELEASE-p一桁でいいのかどうかとか。
>>866 ,867
d、助かりました。
この辺の、サブシェルとリダイレクトの組み合わせは、なかなか慣れない物で。
もはや修行僧の域に思える
シェルスクリプトの初心者なのですがちょっと知恵を貸してください。 入力されたコマンドをwhichまたはtypeでパスを抜き出して そのコマンドのハッシュ値を得るにはどうしたら一番効率がいいですか? 自分で初心者ながら書いてみてるのですが全然うまくいきません。 お願いします。
>>880 bash限定なら、
#!/bin/bash
echo -n 'コマンド? '
read comm
md5sum `type -p $comm`
>>876 >p10とか2桁とかならない範囲なら
なに、この素人
2桁でもできる方法もかけないならプロじゃない。
と素人のおれがいってみる。
必要な時になおせばよい。こういう言い訳が蓄積されて2000年問題が起こった。
>>884 2000年問題とは話が違う。
FreeBSD 5.xはもうEOLになるし、
そもそもシェルスクリプトというのはその場で動けばいいものを
「書き捨て」で書くもの。
質問者はなんちゃってスクリプトで満足したようなので、 後は捏ねくり回したい人たちでどぞー↓
>>884 たとえが悪過ぎ。
ちなみに、2000年問題は、騒がれていたほどの問題は起きず。
ほとんど無害で2000年を迎えた経過した。
2000年問題対策でかかった費用は実は必要なかったことが後でわかった。
むしろ、2000年問題対策と称して儲ける業者がいたことの方が問題。
書き捨てだけじゃなくて、手順を忘れないメモとしても書くぞ。こっちの方が多い。
>>885 あの騒ぎ自体を「2000年問題」と言っている。
ノウハウは自分自身の頭の中に持つもの。 メモは残してはいけない。 変にメモを残して別の担当者に引き継がれると困る。 自分が辞めたらだれもやりかたがわからなくなるのが望ましい。 だから会社は自分を辞めさせられない。
ノウハウってのは惜しみなく与える人の元に集まってくるんだよ。
自分の仕事を他人に割り当てるのではなく、 仕事がすべて自分に割り当てられる。 典型的な下っ端ですね。
>>881 お答えありがとうございます。そのまま書いて実行してみたのですが
そのようなファイルやディレクトリはありませんと出てしまいました。
なんとかなりませんか?
>>894 bashをインストールしていない(/bin/bashがない)のでは?
/bin/bashがないのに #!/bin/bash スクリプトを実行しようとすると、
「そのようなファイルやディレクトリはありません」と出るよ。
自分の仕事を他人に割り当てて楽していた中間管理職はリストラされて行ったけどね
>>895 /bin/bashはあるみたいです。
自分のやりかたが悪いのでしょうか・・・
改行コードは?
あ、それか。/bin/bash^M というファイルを実行しようとするんだよな。 /bin/bash^M というシンボリックリンクを本当に作っておくという方法もあり。
>>899 ありがとうございます。教えていただいたのを参考に
組み込んでみたところハッシュ値は取ってくるようになりました。
以下に書いたのが自分で書いてみたものの一部なのですが
取ってくるハッシュ値と実際にターミナル上でみたハッシュ値が
違うのですが、何が原因でしょうか?
シェルスクリプトはlist.lstに書いてあるコマンドを読んで
ハッシュ値をcachというフォルダにコマンド名で保存するというものなのですが
例えばlist.lstにfindと書いておくとこのスクリプトだと
e1b58755ded5d89cd50789f850232111と出るのにターミナル上でmd5sum findすると
4c66ef9549b37df90fb36ebc06f88ef0と出ます。何度もすいません・・・
#!/bin/sh
BUFIFS=$IFS
IFS=
exec 3<list.lst
while read file 0<&3
do
type -p "$file" | md5sum> cach/"$file".txt
echo "$file [ ok ]"
done
exec 3<&-
IFS=$BUFIFS
echo -e "\n"
>>900 パイプとコマンド置換を混同してるね
× type -p "$file" | md5sum> cach/"$file".txt
○ md5sum `type -p "$file"` > cach/"$file".txt
>>901 ありがとうございます。できました。
パイプとコマンド置換について勉強しなおします。
本当にありがとうございました。
>>901 ,902
パイプとコマンド置換の違いと言う認識だと、
そもそも全然別物なので、
比較検討再構成的な学習法が成立しない。
ようは、引数と標準入力の違いでしょ。
904 :
903 :2009/01/21(水) 20:24:45
$ echo `echo hoge` hoge $ echo 'hoge' | echo $ echo 'hoge' | cat hoge $ cat `echo hoge` cat: hoge: No such file or directory $ って事でしょ。
906 :
903 :2009/01/21(水) 21:00:01
しかし、 type とか md5sum って、 どこのOSの話だ? /bin/bash とかも、変だぞ。 パイプとかコマンド展開とか標準入力とか以前に、 使用するOSとシェルを間違えていませんか?
>>906 おまえ、面白くないからもう書かなくていいよ。
md5sumはともかく、typeコマンド自体は純正シェルにある純正コマンド。
(-pオプションはないけどね)
「コマンド展開」とか間違った用語使わずに、用語も正確に覚えようね。
md5sumはあちこちのソフトウェア配布サイトで使われてるが…
openssl md5 < `type -p "$file"` とでも書いて欲しかったのかな? もちろん、そんなことは知った上で、質問者のレベルを推定し、 質問者に合った回答をするのが上級な回答者。
910 :
903 :2009/01/21(水) 21:25:52
ああ、type は無問題か。
>>905 間違った解決は良くない。
#!/bin/sh
md5 `type -p \`cat list.lst\``
コマンド展開は普通に使うだろ、
チルダ展開と
変数展開と同列のレイヤーの処理だ。
>>910 どこも間違ってないよ。
>>901 よりも早く回答を出せなかったくせに、
後から何言っても言い訳にしかならない。
あと、typeコマンドも知らなかったというお前の程度がこれで知れた。
× コマンド展開
○ コマンド置換(command substitution)
ちなみにチルダ展開は tilde expansion だから、「展開」でよい。
substitutionとexpansionをちゃんと用語として区別すること。
912 :
903 :2009/01/21(水) 21:36:25
間違っている。 ファイル記述子の扱いが二重に無駄。 exec が無駄。while が無駄。 なのにスルーして、手前味噌の話に誘導。 md5sum(そんなコマンド知らんが)の引数と標準入力の 扱いの違いを言及していないで、コマンド展開とパイプの話にすり替えている。 嘘だらけ。
md5は知っててmd5sumは知らないってことはBSDしか使ったことないのか?
>>912 「引数と標準入力の違い」という言い方では、質問者には意味が通じにくい。
で、問題が解決した後で、質問者が「引数と標準入力について勉強してみます」
と言ったとしても、「引数と標準入力」では範囲が広過ぎて、
具体的なパイプやコマンド置換の用法の話に直接結び付かない。
こういう場合は、「パイプとコマンド置換の違い」と、単刀直入に説明するのが、
よい解説者。これなら、後で質問者が、パイプやコマンド置換について、
直接調べて勉強することができる。
>>912 へ。
>>900 の元のスクリプト、もう一度良く見てみろ。
ファイル毎に別々のファイルにmd5を出力してるんだよ。
そうやって質問してるんだから、別々のファイルへの出力が要求仕様。
それに対し、お前の
>>910 の例では、1つのファイルにmd5を書き出すから、
仕様を満たしていない。
whileは無駄ではない。この仕様の場合には必要。
917 :
903 :2009/01/21(水) 21:50:49
>>913 犬もsolも使った事があると言う程度だが、悪いか?
白痴じゃないから、md5sum位はググればすぐに分かるが、
敢えて、/bin/bashという設定に反発しただけで、(typeが勇み足)
真面目にとるな。
>>914 いや、そこが大事。
別に引数と言う概念全般とか標準入力全般やfd0の話ではなく、
あるコマンドが、引数や標準入力をどう扱うかという話しであり、
その方が明らかに調べやすい。
918 :
903 :2009/01/21(水) 21:54:43
>>915 なら、doneの後ろでリダイレクトで十分。
そうしても尚、無駄は残るがね。
>>916 気をつけた方がいい。
職を失うだけでは済まないかも?
コマンドが引数や標準入力をどう扱うかをいくら調べても、 シェルのコマンド置換には行きつかない。 そもそもコマンド置換自体の存在を知らないと、 そういう使い方ができることすらわからない。 だから、「引数と標準入力」じゃなく、「パイプとコマンド置換」と 説明した方がよいことは明らか。
>>918 > doneの後ろでリダイレクトで十分。
もちろんそんなこと知ってるよ。
でもそこは質問のポイントではないので、
焦点をぼかさないように敢えて答えない。
問題になっているのはなぜmd5sumがちゃんと動かないか、だから、
その点を回答すれば良い。
>>912 それを言うなら、IFSだって、わざわざ別変数にバックアップして戻す必要はない。
(どうせシェルを抜ければ関係ないから)
しかし、質問は「このシェルスクリプトの無駄な部分を改良してください」
ではないのだから、そういうことはあえて回答しない。
922 :
903 :2009/01/21(水) 22:05:10
>>920 そんないい加減な。
全体がおかしいいんだから、きちんと添削しないと駄目だろ。
それに、
>>900 の、list.lst のフォーマットも未分明だし、
find と言う行が含まれるのか、
find とだけ書いてあるのかも、
あれだけじゃどちらともとれる。
>>問題になっているのはなぜmd5sumがちゃんと動かないか
こういうのをまさしく手前味噌と言うのだよ。
>>922 >>900 より引用
>取ってくるハッシュ値と実際にターミナル上でみたハッシュ値が
>違うのですが、何が原因でしょうか?
ハッシュ値=md5sum値
として、質問者が聞いているのは md5sumがなぜ違ってしまうか、の点ですね。
その質問にダイレクトに答えてるだけですね。
(手前味噌ではありませんね)
「全体をきちんと添削してください」なんて質問していませんねw
924 :
903 :2009/01/21(水) 22:08:59
>>921 ああ、それもおかしいな。
当然、添削すべき。
単にこちらが、書き漏らしただけだが、
少なくとも、普通は「全部論外」と切って捨てるだろ。
要するに、アピールしたいことの為に
目をつぶったのが正解だろ?
925 :
903 :2009/01/21(水) 22:16:12
>>923 >>何が原因でしょうか?
普通は、それ以前の問題と回答するのが本当の親切。
部分的に正解を教えても、他が論外なのをスルーしたら
質問者が勘違いする元。
ようは、知っている自慢、教えたがりの自己満足。
>>925 >>900 の質問の場合、「それ以前の問題」ではないぞ。
スクリプトは無駄があるとはいえ、
>>901 が回答した急所の1行以外は正常に動作している。
そして、
>>901 の回答によって全体が正常に動作したのだから、
「それ以前の問題」はとくに存在しない。
教えたがりは
>>925 自身じゃないのかw
質問されてもいないことを、
別の回答者が回答して解決した後にわざわざ書き込んで話を蒸し返してるし。
928 :
903 :2009/01/21(水) 22:32:47
>>926 どこが「正常動作」だ?
fd3を開いて閉じる必然性を説明しろ。
929 :
903 :2009/01/21(水) 22:33:58
>>928 仕様通りの出力が得られれば正常動作。
スクリプト内部で無駄があったとしても正常動作かどうかの判断には関係ない。
931 :
903 :2009/01/21(水) 22:44:16
>>930 それは結局「バグ隠し」に繋がる。
コンピュータが期待した動作をするのと、
期待した出力をするのは別物。
バグは潰さないといけない。
>>929 質問者にとって解決ならばそれがすべて。
それを「嘘の解決」と言っているのはお前だけ。
「嘘の解決じゃ駄目だから、真の解決を」なんて言い出すのは、
まさに教えたがりの特徴。
934 :
903 :2009/01/21(水) 22:47:42
まあ勿論、我ら下々の者共よりコンピュータの方が利口なので、 頑張らなくても最適化されている場合が殆どだろうが、 そう言う気概を持ちつづけることは重要。
935 :
903 :2009/01/21(水) 22:52:44
>>932 掲示板では、発呼した質問者の背後に数多の質問者が居ると言うスタンスが肝要。
>>933 知らん。繋がる考え方と言っているだけで、今バグがあると言っている訳じゃない。
>>935 そんな仮想の質問者まで仮定して、
質問されていないことまで解答にこだわろうとするのは
教えたがりの特徴。
いや教えたがりがいるほうが為になっていいですよ
要件定義や要求仕様より、 スクリプトが正しく動くかのほうが大事。 それがこのスレの存在意義。
いくら教えたがりでも、
type -p や md5sumについて知らなかったり、
「コマンド置換」の用語を知らなかったり、
「別ファイルに出力」という要件を読み落すような
レベルの低い教えたがりは要らないな。
あと、本題のmd5sumのコマンドラインの修正点について一切答えず、
本題に関係ない部分の突っ込みばかり入れる
>>903 みたいな教えたがりは要らないな。
>>901 が先に本題の解答をしていなかったら、
>>903 によって、本題以外の突っ込みばかりで
質問者が潰されていたことだろう。
>>928 fd3を開いて閉じる必然性:
while ...
do
:
done < list.lst
の方式では、whileループの中で(readコマンド以外が)
もし本来の標準入力を読む必要があった場合、読めなくなってしまう。
かと言って、while read file < list.lst と書いてしまうと、
ループのたびに list.lstがオープンし直されて頭から読み直されるから正常動作しない。
そこで、exec 3<list.lst で、あらかじめ list.lstをオープンしたままにしておき、
while read file 0<&3 で、readコマンドだけにリダイレクトする。
0<&3は単なるファイル記述子の複製だから、read ... <list.lst とは違って、
ファイルを頭から読み直さないから、正常動作する。
whileループを抜けたら、fd3は必要なくなるので、
exec 3<&- で閉じる。
以上、必然性は認められる。
read a ってやると行頭の空白が $a に入らないんだけど、 うまく空白まで拾う方法ってないんだっけ?
おー、でけた。ありがと。
>>942 ,943
行頭の空白を拾わないと言う認識だと、
そもそも全然別物なので、
比較検討再構成的な学習法が成立しない。
ようは、デリミタ展開の問題でしょ。
>>945 お前まだいたのかw
質問が解決した「後」で蛇足な書き込みする前に、正しい用語覚えろ。
× デリミタ展開
○ 単語分割(word splitting)
>>もし本来の標準入力を読む必要があった場合、読めなくなってしまう。 アフォのこじつけ丸出し。 while read って書いたのは誰だ? 以外のコマンドって何だ? 読む必要とは? おまいは、コマンドの指示に従ってスクリプトを書くのか? 本末転倒。
>>945 ,946
見苦しい自演でご苦労ですな。
しったかをするために、
更に無知な人間をでっち上げるとは、
たいした念の入り様だ。
死ねカス。
>>947 意味わかってる?
本来の標準入力を読むのは、readじゃなくて、
whileループ内の、do 〜 done の間のコマンドのことだよ。
while read file
do
mv -i "$file" "$file"-hoge
done < list.lst
みたいな場合、mv -i コマンドが確認のために標準入力を読んでしまう。
これが、< list.lstと競合して正常動作しない。
これを回避するために fd3 を使う。
>>949 まさに、牽強付会。
read がリダイレクトを読むのが前提で、
do以下が読むのを「本来の」ってのが、無理やりだ。
意味分かってる?
>>950 逆に聞くが、
>>949 のような場合 (ループ中にmv -i がある)
done < list.lst の方式でどうやって書くつもりだよ?
まさかいちいち mv -i < /dev/tty はないだろ?
fd3 (別にfd4以降でもいいが) を使うのが一番美しいだろ?
よって、お前の負け。
てか、まさにfd3が不要だろ。 何でわざわざ競合する状況にしないといけないのか? 普通に標準入力を読むと、困るのか? 特殊なライブラリを無理にリンクして、 レースコンディションを作る趣味でも有るの?
>>952 おい、mv -i の動作、理解してないのかよ。
done < list.lst
の状態で、mv -i が標準入力を読むと、
list.lstを読んでしまう。
で、ファイルリストが読み飛ばされてめちゃくちゃになるだけでなく、
「y」以外のデータが読めた場合は mv コマンドがキャンセルされる。
全く意図通りに動かない。
まずは、
>>951 の質問に答えること。話はそれからだ。
>>まずは、
>>951 の質問に答えること。話はそれからだ。
答える必要無し。
なんで、
>>949 のような場合って言う意味不明の状況に対して、
人様の脳みそを使わせようとするのか?
>>900 でfd3を開いて閉じる必然性が無い事について、
「これこれこういう場合に必然性が有る」というのは、
単なる詭弁。
>>955 >答える必要無し。
なんだ、答えられないのか。お前、負けを認めたなw
>「これこれこういう場合に必然性が有る」というのは、
>単なる詭弁。
詭弁ではない。
お前自身も、
>>931 で、
「それは結局「バグ隠し」に繋がる。」と発言してる。
今現在はバグはなくても、「これこれこういう場合に」にバグが発生する可能性が
あるのをあらかじめ潰しておくことを、お前自身は肯定していたわけだ。
ならば、whileループにおいて、リダイレクトの必要があるのは readだけなのだから、
read以外の、do〜doneの間にあるコマンドはリダイレクトの影響を受けないよう、
標準入力をもとの標準入力のままにしておくことが
将来を見通したバグのないコーディングといえる。
ちなみに、do〜doneの間に mv -i を入れて、インタラクティブに確認するという
スクリプトは、普通にあり得る。
で、そういう場合、fd3を使ってオープンした上で、read 0<&3 で読むというのも、
テクニックとして存在する。
お前は、そのテクニックについて知らなかったわけだ。
なんでも勝ち負けで物事を見るって団塊の世代かよ
一言でまとめると、
>>955 は fd3を使ったwhileループのテクニックについて理解できない。
>>958 出来ていないのはお前。
というか、お前はシェルスクリプトのあらゆる事が、
まったく理解できていない。
やめてしまえ。
>>956 妄想は程々に。
よくもまあ、それだけ嘘ばっかり書けるな。
本当の事が一つも書いていない。
まあ、お前のレスは何時もそうだがな。
>>960 だから、
>>951 の質問に答えろよ。
論破されて答えられなくなったからと言って、
「答える必要なし」で誤魔化すなよw
>>960 は、
whileループ中のループ本体のコマンドが標準入力を読むこともあるという、
ごく普通の状況すら想像できなかったんだろw
もっと想像力を身に付けろ。
シェルスクリプトは、様々な可能性を考慮してコーディングすること。
あと、
>>959 ,960 には、具体的なことが一言も書かれていない。
つまり、全然反論になっていない。
これは、論破された人間が負け惜しみで書く典型的な文章。
もう俺以外は全員勝ちでいいよ
>>900 がIFSを変更したり、ディスクリプタ3番をexecで開いたり閉じたりという
テクニックを知っているにも関わらず、
質問内容自体はごくごく初歩的なのでちょっと驚いた
まわりからシェルスクリプト書くときのルールみたいにして
教え込まれてるのかな?
おそらく、他のスクリプトからコピペしてきたんだと思う。
while read buf do echo $buf done < hogehoge のhogehogeのところをファイルじゃなくてコマンドにすることは可能ですか? これじゃ無理でしたが、イメージはこんな感じです。 while read buf do echo $buf done < `grep . hogehoge`
grep . hogehoge | while read buf do echo $buf done
>>968 ありがとうございます!
ついでにCSVファイルの各レコードのカラム数を出したいんですが、うまい方法ありますか?
awk -F ' { print NF } ' hoge.csv
でもいいんですが、awkが嫌いなので使いたくないです
>>969 sed 's/\\,//' hoge.csv | awk -F, '{ print NF; }'
Text::CSV_XS
>>969 IFS=,
while read line 0<&3
do
set $line
echo $#
done 3< hoge.csv
ちなみに、fd3を使う方式にしといたよw
なら俺はfd4を使う方式で while read line 0<&4 do echo ",$line" | tr -cd "," | wc -c done 4< hoge.csv
fd?言う前に、"\,"エスケイプくらい処理しろ。
>>974 質問は、
>>969 が言うように、
> awk -F, '{ print NF }' hoge.csv
>でもいいんですが、
なのだから、↑のawkと同等のシェルを作ればいいだけ。
エスケイプなんて余計なことする必要なし。
スクリプトを略すな
>>975 そんなら、とっとと「awkと同等のシェル」作れ。
>>974 Excelで読めないようなCSVはCSVとは認めません。
>>976 awkと同等のものがスクリプトなわけないだろ。
シェルでいいんだよ。
シェルとも限らないのでは
おでん?
おでん!?
今の時期はやっぱりおでんじゃない?
>>980 次スレ立ててよ。
スレ伸びてるなーと思ってきたが
とりあえず、
>>903 が、分かってないのに偉そうなところまで読んだ