1 名前:名無しさん@お腹いっぱい。 [2009/07/01(水) 09:42:48 ] シェルスクリプトの総合スレです。 スクリプトのお勉強・自慢・腕試しなどにどうぞ。 まずは注意点、リンク、地鎮祭など(>>1-6 くらい)をご覧ください。 □お約束 ・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。 bash/zsh/ksh/ashなどに依存する場合は明示しましょう。 Linuxユーザは/bin/shの正体がbashなので特に注意。 FreeBSDユーザは/bin/shの正体がashなので注意。 v7 shに一番近くて、現役のshは、OpenSolaris由来のheirloom sh。 src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/sh/ heirloom.sourceforge.net/sh.html ・csh/tcshのシェルスクリプトは推奨されません。 (理由は「csh-whynot」でググれ) ・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。 manや参考リンクを見ましょう。 aproposないしはman -kでそれらしい単語による簡単な検索もできます。 ・シェルスクリプトのことをシェルってゆーな ・シェルで使えるワイルドカード等は正規表現ではありません。 正規表現の話題はスレ違い(正規表現スレへ) □初心者へのアドバイス: ・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも RubyやPerlの方が適した仕事には素直にそちらを使いましょう。 ・知らないコマンドが出てきたらmanを引きましょう。 ・思い通りに動かないときは、まずは sh -x でトレースしましょう。 前スレ シェルスクリプト総合 その14 pc12.2ch.net/test/read.cgi/unix/1233179688/
532 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/04(日) 18:05:40 ] >>529 例えば一行の処理毎に、シェルスクリプトでは外部コマンドを起動する必要がある、 perlでは不要。というような場合、データが大きくなればperlの方が速くなる。
533 名前:529 mailto:sage [2009/10/04(日) 18:31:28 ] >>532 それはテキストの一行に対して処理する事に対し、シェルスクリプトならその行数分外部コマンドが実行、 つまりシェルスクリプトでテキストの1行に1コマンド処理実行させてる場合、 100行なら100回外部コマンドが実行される事になるが perlなら1コマンド?で処理が終了するので大きいテキストに対してだと 処理スピードに差がでるって事でしょうか?
534 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/04(日) 18:45:38 ] テキストの一行じゃないんじゃないの。sedもawkも複数行を処理できるでしょ。 あとマルチコアプロセッサとかだと、プロセスが分かれていた方が処理が早く 終わったりもするね。 キッチンシンクアプローチとツールボックスアプローチを調べてみると良いと思うよ。
535 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/04(日) 18:58:02 ] >>533 そう。プロセスの生成は非常にハイコスト。
536 名前:529 mailto:sage [2009/10/04(日) 19:12:23 ] >>534-535 ありがとう。 うーん、でも完全に理解し切れてない。 何かを実現させる時、シェルスクリプトの場合複数のコマンド発行(プロセス起動)が perlなら少プロセスで可能な場合(主にテキスト処理などで)があるって事でしょうか? >キッチンシンクアプローチとツールボックスアプローチを調べてみると良いと思うよ。 調べてみます。
537 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/05(月) 00:38:28 ] python
538 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/05(月) 02:27:03 ] オライリーのミニマルPerlって本があって、 sh&sed&awk の粗探しをして Perl への移行を薦めるような内容なんだが、 これ読むと逆に、とくに大規模でもないテキスト処理なら シェルで無問題じゃんって感じなんだよね。 Perlが受けたのは、第一に実装が優秀で速かったのと、 あと Perl はベル研系の厳格な雰囲気がないというか、 何となく書いて動いちゃうとこがある。そのへんの寛容さが人気の秘密かと
539 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/05(月) 15:57:27 ] 結局適材適所と、それを判断出来る能力の問題だと思うよ。 シェルスクリプトで遅いなら、perlなりでやる。それでも遅いならCとか。
540 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/05(月) 18:06:14 ] echoで最後に改行したくない場合、 echo -n "unko" では期待通りに出力されるのですが、 echo "unko\c" だとunko\cと改行して出力されてしまいます。 Cygwinで\cに対応させるにはどうしたらよいでしょうか。 よろしくお願いいたします。
541 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/05(月) 18:15:13 ] >>541 CygwinということはGNU coreutilsのechoか。 -e オプション?
542 名前:540 mailto:sage [2009/10/05(月) 19:05:48 ] >>541 おおお、ありがとうございます。 $ echo -e "unko\c" で期待通り unko$ と出力ができました。 本番の環境はHP-UXを使用しておりまして、 逆に-eオプションが無い(?)ため、 $ echo -e "unko\c" とした場合、 -e unko$ と出力されてしまいすが、とりあえず、 alias echo='echo -e' で解決いたしました。 ありがとうございました!!!!
543 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/05(月) 21:56:31 ] そのへんの移植性に関するバッドノウハウはGNU autotoolsに詰まってる。
544 名前:名無しさん@お腹いっぱい。 [2009/10/21(水) 12:16:25 ] RCSで、チェックイン済みの最新リビジョンと、そのひとつ前のリビジョンを比較 ということをよくやります。 今は、rlog -r fileで最新リビジョン番号を調べて、たとえば 1.123 だったとすると、 頭の中でリビジョンを1引いて、rcsdiff -r -r1.122 file みたいに実行しています。 これを1発でやるシェルはできませんか? あ、sed/awk等でゴニョゴニョやる方法じゃなく(それしかないなら自分でやるので)、 奇麗にエレガントにやる方法を希望します。
545 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/21(水) 18:10:19 ] よく知らないで申し訳ないが current=`rlog -r file | grep 'なんとか'` current=`expr $current - 0.001` rcsdiff -r -$current file 空白とか改行とか考慮せずかなり適当に書いたけど。 exprでできないならbc使えばできるかもしれない。
546 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/21(水) 18:32:38 ] それはエレガントじゃないらしいよ
547 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/21(水) 20:25:10 ] シェルってゆうな。クズ。
548 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/21(水) 22:12:01 ] エレガントさが求められていたのか 知らんかったよ、すまん
549 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/21(水) 22:41:49 ] 奇麗でエレガントな質問を募集します。
550 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/24(土) 13:10:57 ] >>545 エレガント云々を除いてもそれじゃ駄目だよ。 リビジョン番号は、 1.8 1.9 1.10 1.11 ... 1.99 1.100 1.101 ... って進むから、expr で 0.001 引くのは全然見当違い。
551 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/26(月) 22:08:08 ] どうしてもわからないので質問させてください。 #!/bin/sh DIR=`pwd` cd $DIR/file ./play のようにC言語で記述したplayファイルを実行しているのですが play内では簡単に表すと以下のような処理をしています while(true){ ファイルの読み込み処理 sleep(1); } このように1秒ごとにファイルを監視してるのですが シェルスクリプトで実行すると1秒待たずにwhileループが回っているのですが どうすればよいのでしょうか?
552 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/26(月) 22:13:23 ] >>551 そのwhileループの具体的なスクリプトを出さずに質問したいなら、 エスパースレに池。 sleepコマンド自体が文法またはオプションエラーになってて 1秒待ててないんじゃないの?
553 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/26(月) 22:15:27 ] 問題点を人に伝える能力が欠けすぎ
554 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/26(月) 22:17:39 ] >>552 whileループはC言語で書いてるんだろ。(プログラムは出てるじゃん) コマンドラインで直接 ./play を実行すると1秒毎に処理されるのに、 >>551 のシェルスクリプト経由で ./play を実行すると1秒待たずにループする、 という話だろ。
555 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/26(月) 22:20:28 ] で、答えは?
556 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/26(月) 22:20:58 ] >>551 sleep()関数はシグナルで中断される可能性がある。 シグナルが到着すればsleep(1)は1秒未満で終了する。 代わりにnanosleep()使え。 たぶん、シェルスクリプト経由の時だけシグナルが発生するような 別の条件が加わってるんだろ。
557 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/26(月) 22:36:54 ] >>551 play コマンド側は特に何もせずシェルスクリプト側で sleep 1; すればいいんじゃね?
558 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/26(月) 22:58:35 ] >>556 ありがとうございます。 試してみましたが同じ状態になりました。 説明が不足していてすみません GNU Chessを改造していたので、その部分のコードを切り抜いても分かりづらいので自分なりに説明したのですが、説明力がなくてすみません。 ファイルの読み込み部分の処理は while(true){ sleep(1); if(rlogfp=fopen("./black.log","r")){ fgets(inp, MAXSTR, rlogfp); fclose(rlogfp); remove("./black.log"); break; } } black.logというのは次の手を指定した文字列が収められているファイルです。 C言語で書くのもうまくないので下手なコードですが、ご了承ください。
559 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/26(月) 23:01:09 ] >>557 whileで監視しているのでsleep(1)がないとファイル作成時に読み込みが実行されるのか、うまくデータが受け取れないので sleep(1)を追加している次第です。
560 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/26(月) 23:39:32 ] 後からこんなことを追加するのはすみませんが どうやら監視しているファイルが存在しないのに、ファイルがあるように動いているみたいで、 ファイル読み込む→whileを抜け出す→間違った手だと解釈→whileに入りファイルを読み込む を繰り返すようになっているみたいです。 シェルスクリプトではなくターム上で実行するとうまくいくのに スクリプトだとこの現象がおこるのはどういったわけでしょうか?
561 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/26(月) 23:56:55 ] >>560 シェルスクリプトの cd $DIR/file あたりがうまく行ってないとか。 別のディレクトリの black.logを読んでループしてるとか。
562 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/27(火) 00:11:19 ] >>561 レスありがとうございます 他のディレクトリではblack.logは生成していないのでそのケースはないかと思います ディレクトリの場所も間違いはないです
563 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/27(火) 00:23:15 ] sleepはループの先頭なの?それなら確実に1秒待つでしょ? 説明に一貫性がないと回答者も混乱するし、いいことないよ。 あとは、fgets, fclose, removeの戻り値をちゃんとチェックしてみる。
564 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/27(火) 00:30:07 ] ぱおーん ってそれはエレファント
565 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/27(火) 00:40:24 ] >>551 >シェルスクリプトで実行すると1秒待たずにwhileループが回っている これはどうやって確認したの? 原因を切り分ける為に、問題を再現出来る最小限の プログラムを作ってみると良いと思うよ。
566 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/27(火) 00:46:46 ] >>563 ,565 アドバイス通り明日調べてみます。
567 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/27(火) 08:05:15 ] >>559 > whileで監視しているのでsleep(1)がないと > ファイル作成時に読み込みが実行されるのか、 > うまくデータが受け取れないので busy waitになるだけでちゃんと動くはずだろ。 だから動かないのは、sleep()以外のところがおかしい。
568 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/27(火) 11:08:26 ] そのファイル、NFS かなんかの領域に置いてないか? おかしなキャッシュが効いてるような気がする。
569 名前:名無しさん@お腹いっぱい。 [2009/10/27(火) 11:38:40 ] >>568 特に変わった場所には置いてません。 とりあえずthreadやwhileループとファイルの読み込みの部分だけ同じ形でtestファイルを作ってみたのですが 直接実行、シェルスクリプトで実行で共に問題がなかったので、もっと別の場所だと分かりました。 もう少し試行錯誤してみたいと思います。
570 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/27(火) 12:26:31 ] ちょっと説明が長くなるのでアップロードしてみました。 お手数をおかけしてもうしわけありません。 DLkey:unix www1.axfc.net/uploader/Sc/so/49655.txt
571 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/27(火) 13:04:39 ] input_threadが動き出す前にwait_for_inputに入ると、 input_statusが初期値(INPUT_NONE)のままなので、whileを抜けてしまう。
572 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/27(火) 21:14:09 ] test が表示されないという現象はウチでは一度も再現しませんでした。 Dual Core の Mac です。 外してたらスマソ。 test.sh を実行する Ctrl-C で test.sh を止める a.out のプロセスは残ったまま とかじゃないよね? まあそれでも test が表示されない理由にはなりませんけど。
573 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/27(火) 21:50:45 ] 一度目がその症状があって もう一度試したら治っていました >>571 どのように記述すれば回避できるのでしょうか? 丸投げのようですみません^^;
574 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/28(水) 00:03:20 ] 以前動作していたスクリプトが動かなくなってしまいました… ここ最近kshのアップデートを行ったのが原因なのでしょうか… 何か情報をお持ちの方いらっしゃいましたらご教授願います。 <事象> 特に問題なく見えるkshがsyntax Error `(' unexpectedで異常終了 コメント内のスペースを1つ削除or2つ追加すると正常に動作する <やったこと> kshとbashのアップデート ksh 20060214-1.4 → 20080202-14.el5 bash bash3.1-16.1 → bash3.2-21.el5 <環境> redhat Linux 5.1 uname -a結果 Linuc 2.6.18-53.el5 #1 SMP Wed Oct 10 16:34:19 EDT 2007 x86_64 x86_64 x86_64 GNU/Linux <備考> ksh -nで構文チェックをかけると、構文エラー以外に「" quote may be missing」という警告が必ずついてきます。 コメントを弄ってエラーを抑止するとこの警告も発生しなくなります。
575 名前:551 mailto:sage [2009/10/28(水) 00:05:16 ] . play.shで実行したらうまく動きました。 結局原因はわかりませんでしたが、サブシェルだと何か環境とちがったのかな?と素人ながら思います。 お騒がせしてすみませんでした。
576 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/28(水) 00:59:40 ] それたまたまだから
577 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/28(水) 01:16:52 ] while(true)なんてしないで、openの返り値でなんとかならんの?
578 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/28(水) 07:06:37 ] >>574 おいおい、redhat 5.1というのは10年くらい前のOSで、 カーネルは2.0の時代のもの。(libc5からやっとglibc2に変わった時代) カーネル2.6で動くわけがない。
579 名前:574 mailto:sage [2009/10/28(水) 11:18:44 ] >>578 今確認したところ、redhat 5.1ではなく RHEL 5.1でした redhatLINUXとRHELを混同していました 申し訳ありません
580 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/28(水) 11:43:19 ] >>574 スクリプト晒せ
581 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/28(水) 11:44:15 ] libc5なつかしいな。 glibc2(libc6)になってようやくLANG関係がマトモになったんだっけ
582 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/28(水) 11:44:22 ] どうせShift_JISのコメントだろ。
583 名前:574 mailto:sage [2009/10/28(水) 23:54:47 ] >>580 手元にスクリプトがない上に動く動かないの条件がよく分からないので再現できず… 申し訳ないです。 >>582 コメント等もう一度文字コードを見直しましたが、すべてUTF-8でした。
584 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/28(水) 23:56:51 ] 手元にスクリプトがないのにコメント等見直した?意味が分からんのだが
585 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/28(水) 23:57:32 ] 不思議な話だなw
586 名前:名無しさん@お腹いっぱい。 [2009/10/29(木) 22:50:29 ] LOTO6用の数字列を生成する for x in $(seq 1 5); do echo $(seq 1 43 | shuf | head -6 | sort -n); done
587 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/10/30(金) 23:17:20 ] >>586 for((i=0;i++<5;)){ echo `shuf -i 1-43 -n 6 | sort`; } ↑の方が簡単
588 名前:名無しさん@お腹いっぱい。 [2009/11/10(火) 09:10:20 ] 質問です。記法1と2では違いがありますか?どちらが正しいとか… doの後に改行入れるべきかどうなのか,ということですが。 記法1 for i in * do echo $i done 記法2 for i in * do \ echo $i done
589 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/10(火) 09:48:42 ] >>588 記法2は間違いではないがバックスラッシュが余分。 もともと do の直後には、空白、タブまたは改行の区切り文字があればなんでも良い。 「行の継続」をする必要はないので、バックスラッシュは不要。
590 名前:588 mailto:sage [2009/11/10(火) 11:02:41 ] >>589 ありがとうございました。
591 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/10(火) 11:33:58 ] 今のトレンドは↓の書き方。 bash依存じゃないぞ。純正シェルでもちゃんと動くから安心して使え。 for i in * { echo $i }
592 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/10(火) 11:37:50 ] どこのトレンドだよwwwww
593 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/10(火) 11:43:46 ] for は { ... } でもいいけど、 while は do ... done じゃないといかんというのがアレ。
594 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/12(木) 08:07:11 ] kshで標準出力と標準エラーをデフォルトでファイル&画面に出力するやり方はありますか? 毎行、| tee -a hoge.log を書くのが大変なので。
595 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/12(木) 08:19:07 ] >>594 ( command1 command2 command3 : ) 2>&1 | tee -a hoge.log
596 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/12(木) 08:41:02 ] >>594 scriptコマンドは?
597 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/12(木) 08:58:07 ] 俺はそういうとき telnet localhost | tee hoge.log ってやってる
598 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/12(木) 09:27:34 ] 正解(>>595 )が出た後にボケ回答(>>596-597 )が出てくる、の法則
599 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/13(金) 19:18:09 ] 自分よりいい答えが出たのがそんなに悔しかったのか
600 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/13(金) 19:57:03 ] > 毎行、| tee -a hoge.log を書くのが大変なので。 毎行と言っているし、ここはシェルスクリプトスレなのでスクリプトの中での記述に 関しての質問だと言う事が容易に予想できる。 スクリプトに関しての質問にscript使えだの、telnetをリダイレクトしろだの、 ボケまくりの回答してる奴らは何なのだろう? 匿名掲示板だからボケ回答も恥ずかしくないのだろうか?
601 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/14(土) 03:03:51 ] 必死だなw
602 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/20(金) 10:11:52 ] >>599 只の知ったかだろ 半角数字とか学生の分際で早くも理系気取りかよ
603 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/20(金) 10:44:29 ] >>602 日本語で頼むわ……
604 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/20(金) 20:00:12 ] > 半角数字とか学生の分際で早くも理系気取りかよ これは新コピペになりそうな気がする
605 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/21(土) 01:23:51 ] >>604 新コピペとか学生の分際で早くも理系気取りかよ …こんな感じ?
606 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/21(土) 02:02:27 ] bashを使用しています。 数字が入っている変数に3桁毎にカンマを入れる方法が分かりません。 どうやれば3桁毎にカンマを入れれるようになりますか?
607 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/21(土) 12:27:50 ] >>606 printf "%'d" "$var"
608 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/21(土) 22:05:46 ] >>607 これはいいことを聞いたと、試してみたができないぞ? $ bash --version GNU bash, version 4.0.28(2)-release (i686-pc-linux-gnu)
609 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/21(土) 22:13:00 ] >>608 varの中にちゃんと数字入れてるか?
610 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/21(土) 22:17:56 ] >>607 では printfの書式に改行が入ってないから、 シェルのプロンプト設定によってはprintfの出力をプロンプトが上書きしてしまう とエスパー。 それとは別に、zshの内蔵printfでは動作しないね。
611 名前:606 mailto:sage [2009/11/21(土) 23:23:18 ] >>607 さん 有難うございました。ウチの環境ではうまくいきました。
612 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/22(日) 14:57:44 ] $ printf "%'d\n" "123456" 123456 $ var="12345667" $ printf "%'d\n" "$var" 12345667 なにがいけないのかねー
613 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/22(日) 17:20:06 ] $ printf "%aqd\n" "123456"
614 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/22(日) 17:29:35 ] >>612 localeの設定じゃない? printf(3)によると、 >>printf("%'.2f", 1234567.89); >>results in '1234567.89' in the POSIX locale, in '1234567,89' in the nl_NL locale, >>and in '1.234.567,89' in the da_DK locale.
615 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/23(月) 00:52:46 ] >>614 ロケールの問題でした。ありがとう。 ちょっと気になるのは、printfコマンドする時に LC_ALLを明示的に与えても上手く動作しなかったんですよね 組み込みコマンドだと伝わらないのかな? $ locale LANG=ja_JP.eucJP LC_CTYPE="ja_JP.eucJP" LC_NUMERIC=C LC_TIME=C LC_COLLATE="ja_JP.eucJP" LC_MONETARY="ja_JP.eucJP" LC_MESSAGES=C LC_PAPER="ja_JP.eucJP" LC_NAME="ja_JP.eucJP" LC_ADDRESS="ja_JP.eucJP" LC_TELEPHONE="ja_JP.eucJP" LC_MEASUREMENT="ja_JP.eucJP" LC_IDENTIFICATION="ja_JP.eucJP" LC_ALL= $ LC_ALL=da_DK printf "%'d\n" "123456789" 123456789 $ LC_ALL=da_DK bash $ locale LANG=ja_JP.eucJP LC_CTYPE="da_DK" (省略) LC_ALL=da_DK $ printf "%'d\n" "123456789" 123.456.789
616 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/23(月) 06:55:47 ] $ printf "%'d" "123456789" printf: %': invalid directive
617 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/23(月) 13:08:26 ] >>615 >>$ LC_ALL=da_DK printf "%'d\n" "123456789" LC_ALL を LC_NUMERIC にしてもダメ?
618 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/23(月) 15:32:07 ] (優先される)強さは、 強 LC_ALL > LC_個別 > LANG 弱 のはずだから、LC_ALL があってダメなら LC_NUMERIC でもダメな希ガス。
619 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/23(月) 15:44:54 ] >>617 ダメでした。 というかlocale(7)に書いてあるロケールの決定順序を見る限り $ LC_ALL=da_DK printf "%'d\n" "123456789" で動かなければ、LC_NUMERICを使っても同じなのではないかと。 ところで、 $ LC_ALL=da_DK locale の結果は$ LC_ALL=da_DK bashで作ったシェル上でlocaleした (参考>>615 の2個目のlocale)のと同じ結果になります。 (つまりLC_ALLも、LC_NUMERICもda_DK) その癖に、 $ LC_ALL=da_DK printf "%s\n" "$LC_NUMERIC" と $ LC_ALL=da_DK echo "$LC_NUMERIC" はどちらも「C」が出力 (参考>>615 の1個目のlocale)になるんですよね。LC_ALLはもちろん、改行のみです。 環境変数の伝わり方が変ですよね? つまり、 localeだとLC_ALL(もしくはLC_NUMERIC)がexportされてて、 printfとechoはexportされない。 それと、 >>615 で「組み込みコマンドだと・・・」といいましたが、 $ type -a echo したら、builtinと/bin/echoの2つのエントリがあったので、 どちらも試してみましたが、exportされませんでした。 どういうメカニズムでこうなっちゃうんでしょう。
620 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/23(月) 15:54:16 ] >>618 とレスが一部被ってしまった 連レスですみませんが、 コマンドの前に環境変数定義をつけるシンタックスって なんという名前で呼ばれていますか? そもそもどういうものなのかを調べたいのですが、ググりづらくて。
621 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/23(月) 16:04:31 ] >>620 shじゃなくてbashのマニュアルで申し訳ないが、 A simple command is a sequence of optional variable assignments followed by blank-separated words and redirections, and terminated by a control operator. だそうな。 optional variable assignments (省略可能な変数代入)
622 名前:608,612,615,619 mailto:sage [2009/11/23(月) 18:22:28 ] >>621 ありがとう。man bash読みました。 組み込みコマンドでの、optional variable assignmentの挙動についてまとめてみました。 COMMAND EXECUTION ENVIRONMENT節に以下の記述があります。 When a simple command other than a builtin or shell function is to be executed, it is invoked in a separate execution environment つまり組み込みコマンドはseparate execution environmentで呼び出されない。 これは当たり前のことで、組み込みコマンドは別シェルで実行されないということですよね。 そして個人的に新たに知ったのは、optional variable assignmentは別シェルにしか 伝えられないということです。(現在のシェル変数には代入されない) だから、>>615 で $ LC_ALL=da_DK printf "%'d\n" "123456789" がコンマ区切りにならなかったんですね。 だったら、敢えてシェル変数を伝えられた実行環境を作って、printfするとどうなるか。 #include <stdlib.h> int main() { system("printf \"%s\n\" \"$LC_NUMERIC\""); system("printf \"%'d\n\" \"123456789\""); return 0; } をコンパイルしたa.outに対して試してみました。 (a.outは組み込みコマンドではないので別シェルで実行され、 optional variable assignmentが伝えられる)
623 名前:608,612,615,619,622 mailto:sage [2009/11/23(月) 18:25:17 ] $ ./a.out C 123456789 $ LC_NUMERIC=da_DK ./a.out da_DK 123.456.789 $ LC_ALL=da_DK ./a.out C 123.456.789 となりました。 >>615 の後半のようにLC_ALL=da_DK bashで環境作ってからやる方が楽なので、 本末転倒になりましたが。。。 ところで、これで興味深いのは、LC_ALLはLC_NUMERICに影響を及ぼさないことです。 >>615 では LC_ALL=da_DK bash 後にlocaleすると、LC_ALL=LC_NUMERIC=da_DKになりますが、 bashの初期化処理でLC_ALLの値をLC_NUMERICにコピーしているのかも? 最後に。619の訂正。 SIMPLE COMMAND EXPANSIONの節の 4.にあるように、 parameter expansionされてからコマンドが実行されるようなので、 $ LC_NUMERIC=da_DK printf "%s\n" "$LC_NUMERIC" はコマンドが実行される前に引数の$LC_NUMERICが「C」(参考>>615 )と展開される。 そのため、Cが表示される。 長文失礼しました。
624 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/23(月) 18:52:34 ] 組み込みコマンドがseparate execution environmentで呼び出されないのは bashの場合の話。 kshでは組み込みコマンドでもseparate execution environmentで動作する。
625 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/23(月) 19:12:34 ] やはり、sh系といえども、何を使っているかは明示すべきなんだな。
626 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/23(月) 19:17:36 ] 確かにその通りですね。 上は全部>>608 の環境で試してた。
627 名前:名無しさん@お腹いっぱい。 [2009/11/26(木) 14:47:50 ] "aa-1125.txt" "aa-0001.txt" "aa bb-1125.txt" "aa bb-0001.txt" "aa bb cc-1125.txt" "aa bb cc-0001.txt" 同じディレクトリにこの6ファイルがあるとします。 この中から「aa bb-????.txt」の形式で且つ最も新しいファイルを 探したいんですが、 (当然のことですが)ls -ltr "aa bb-????.txt"|tail -1とやるとエラーになってしまいます。 どうすればいいでしょうか?シェルはbashです。
628 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/26(木) 15:01:32 ] ls -ltr (ここに6個のファイル名を羅列)|tail -1
629 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/26(木) 15:01:41 ] ls -lt aa\ bb-????.txt | head -1
630 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/26(木) 15:14:14 ] bbの無いファイルもあるぞ
631 名前:名無しさん@お腹いっぱい。 mailto:sage [2009/11/26(木) 15:28:45 ] あるよ だから?
632 名前:名無しさん@お腹いっぱい。 [2009/11/26(木) 15:49:56 ] 申し遅れましたが、 実際にはファイル数、ハイフンより前の部分のファイル名は不定です。 >>627 は単純化した例です。 >>627 の時点で知りたかったことは自動でエスケイプする方法もしくはそのコマンドです。