すいません 下で foreach (a..c) { と書いているのは foreach ('a'..'c') { と書かないと怒られます。(警告だけで、動作はするようです) ようは、a、b、c は変数の名前でなく文字列で、 %aa、%bb、%cc というハッシュのキーですね。 %aa というハッシュの、キーが 'a' の値にアクセスするには $aa{'a'} と書きます。ただしこの場合 a はハッシュのキーであると はっきりしているので $aa{a} と省略形で書けます。 同じハッシュでキー x の値に 550 を、キー y の値に 660 を入れるには キーと値を交互に指定するリストを使って %aa = ('x', 550, 'y', 660); と書きますが、キーと値の関係をはっきりさせるために カッコの変わりに => という記号を使えば %aa = ('x' => 550, 'y' => 660); と書けます。で、この場合は => の左側はハッシュのキーなので 省略して %aa = (x => 550, y => 660); とも書けるわけです。 でも、この '' 省略方式だと、 空白を含むキーが使えません。 %kg = ('yamada tarou' => 80, 'satou tamao' => 50); だと $kg{'yamada tarou'} に 80 が、$kg{'satou tamao'} に 50 が 入りますが、 %kg = (yamada tarou => 80, satou tamao => 50); だとエラーが出て動きません。 $kg{yamada tarou} も怒られて動きません。 下のプログラムで a, b, c というのは、 ハッシュのキーで「文字列」であることを覚えておいてください。 |
ふくしさん、 こんにちわ map の使い方はまだ理解できませんが ★のコードは理解できました。 ありがとうございました。 |
はじめまして。 2日前から調べているのですが、解決できずにここにたどり着きました。 CGIからCGIへデータを渡す際に print "Location: test.cgi?data=1\n\n"; ではなくPOSTでデータを渡したいのですが Socketを使うというのを発見し、いろいろ試したのですが まるで駄目です。(Socket自体、今まで使用したことも無いので(^^;) 具体的には送信元のCGIをindex.cgi、受信するCGIをtest.cgiとしますと index.cgiに下記のような記述をしてみたのですが test.cgiには何を書いてよいのかすら分かりません。 ご教授頂けないでしょうか よろしくお願いします。 ================================ #!/usr/local/bin/perl use Socket; $server='www.*****.com'; $port = 80; $port = getservbyname($port,'tcp') unless $port =~ /^\d+/; $iaddr = inet_aton($server) or die "$serverは存在しないホストです。\n"; $sock_addr = pack_sockaddr_in($port,$iaddr); socket(SOCKET,PF_INET,SOCK_STREAM,0) or die "ソケットを生成できません。\n"; connect(SOCKET,$sock_addr) or die "$serverのポート$portに接続できません。\n"; select(SOCKET); $|=1; select(STDOUT); $file='test.cgi'; $query='data=1'; $len=length($query); print SOCKET "POST $file HTTP/1.0\r\n"; print SOCKET "Content-Length: $len" . "\r\n\r\n"; print SOCKET "$query"; ================================ |
こんな感じでは? if ($ENV{'REQUEST_METHOD'} eq "POST"){ read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); } @pairs = split(/&/, $buffer); foreach $pair(@pairs){ ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $FORM{$name} = $value; } $data = $FORM{'data'}; って、よくある掲示板のパターンですけど。(はずしてたらごめんなさい) というより、index.cgi は普通にフォームを使うだけでことは足りないのでしょうか? (Socket を使わずに) |
補足・その他です(^^; main.cgi→index.cgi→test.cgi となっていて main.cgiでフォームを使いindex.cgiにpostでデータを送信しています。 この受け取ったデータをtest.cgiにそのまま渡したいのですが、 その方法で悩んでいます。 test.cgiはメンバー入り口で受け取った会員ナンバーによって それぞれのページデータを読み込み表示するスクリプトになっていますので 直接 http://***.com/test.cgi?ID などとされて入室されるのは避けたいのです さらに考えた結果、index.cgiとtest.cgiをまとめてしまえば良い事に気付きました(^^; ですが、今後の為にもSocketを使えるようになりたいので もうちょっと努力してみます。 iwtaさんありがとうございます。 受け側では標準入力で良いのですね。 <SOCKET>をいろいろいじってみたりしてました。。。 ということは受けるほうでは use Socket; は不要なのでしょうか Socketの文献をいろいろ読んだのですが、POSTについての情報がどこも少なく (英文は読んでませんが) いろいろとお尋ねしてお手数をおかけします。 |
>>2232 名無しさん ご指摘ありがとうございます。どうやってわかりやすく説明するかは 非常に悩むところですね。autoflush は「存在自体あまり知られてない」 という痛い欠点があり、難しいところです。次回更新時に何かしら わかりやすい解説を書きたいと思っています。 >>2235 H-Hash > このたび、RFC2616の日本語訳のURLが > http://www.studyinghttp.net/rfc_ja/2616/ に変更いたしました。 ご連絡ありがとうございます。修正いたしました。 >>2236 Ka23 > UNIX プログラミング FAQのサイトが > http://www.adl.rd.nacsis.ac.jp/~moro/unix-programmer/faq-j_toc.html > に移転しているようです。 こちらもありがとうございます。後ほど修正しておきます。 >>2243 sio test.cgi は同じサーバにあるのですか? で、ブラウザから直接呼び出すこと はないのですか? ならば CGI じゃなくてただのスクリプトですので、 main.cgi からは open(IN, "/foo/bar/test.cgi ID |"); と呼び出せばいいでしょう。ソケットを使う必要はありません。 もし test.cgi が同じサーバにあって、これまでは CGI として動いていたけ ど、これからはブラウザから直接参照させたくない、ということならば、 $ENV{REQUEST_METHOD}='GET'; $ENV{QUERY_STRING}='data=1'; open(IN, "/foo/bar/test.cgi |"); と、WWW サーバの代わりに適切な環境変数をセットしてからスクリプトを実行 してやればよいでしょう。 test.cgi が別サーバにあるならば、直接スクリプトを実行することはできな いので、そのときはソケットを使いましょう。 > print SOCKET "POST $file HTTP/1.0\r\n"; > print SOCKET "Content-Length: $len" . "\r\n\r\n"; > print SOCKET "$query"; 送ったはいいけど、これでは結果を受け取っていませんし、ブラウザに何も表 示していません。 while (<SOCKET>){ # ヘッダを捨てる m/^\r\n$/ and last; } print "Content-type: text/html\n\n"; while (<SOCKET>){ # ボディのみ表示 print $_; } とかいうのをこの後に付けて下さい。 > POSTについての情報がどこも少なく あまり書くことがないからでしょう。気を付けるのはContent-length を付け ること、くらいじゃないでしょうか。 あと、CGI 経由で HTTP クライアントを開発するのはやめましょう。まずはコ マンドラインから動くような HTTP クライアントを作り、完成したら CGI 経 由でも動くように改造しましょう。でないと、問題の切り分けが非常に面倒に なります。 |
68userさんありがとうございます。 やりたい事が全てご指摘通りです(^^; open関数のパイプの使い方すら知りませんでした。 今やっと説明されているページを見つけ http://www.kt.rim.or.jp/~kbk/perl5.005/perlipc.html 勉強中です。 Socketについてもようやく理解できました。 データを受け取った側で、ブラウザ処理をしようとするから 訳が分からなくなっていたようです。 今日はperlに浸かり勉強する日にします p(..) |
X Window Systemを立ち上げるときに、 (**) stands for supplied (--) stands for probed/default values (**) ... (**) ... というメッセ-ジが出て立ち上げることができません。 これはいったいどういうことなのでしょうか。 |
正確には (**) stands for supplied, (--) stands for probed/default values (**) ... (**) ... でした。 |
>>2247 sio > データを受け取った側で、ブラウザ処理をしようとするから > 訳が分からなくなっていたようです。 まず、全体の構成を見直すべきでしょうね。 - main.cgi に統合する。 - test.cgi はユーザ名を引数で受け取り、ログイン可能なら 戻り値 0 を、ログイン不可なら戻り値 1 を返す。 などと現在の仕様を比べ、一番良さそうなものを採用しましょう。 >>2249 初心者 > (**) stands for supplied, (--) stands for probed/default values それは起動時に (成功・失敗にかかわらず) 必ず表示されるメッセージです。 また、OS などの環境が何も書いていないので、答えられる人は いないでしょう。 # 僕は XFree86 やらビデオカードやらには詳しくないので、 # 書いてもらっても答えられないかもしれませんが。 |
こんにちは。いつもお世話になってます。 Perlについて質問があります。 各ファイルに ”ー1”と ”ー2”が含まれた行があって、それを区切りに2つのファイルに分けたいのですが、なかなかうまくいきません。 EXAMPLE: *File0001の内容ーー 0001ー1 C100 Open C101 NG 0001ー2 C102 Open C103 Open *File2の内容ーー 0002ー1 C200 Open C201 NG C202 Open 0002ー2 C203 Open C204 NG この0001と0002の2つのファイルを0001ー1と0001ー2、0002ー1と0002ー2の4つのファイルに分けたいのです。 下のスクリプトは全然間違ってるのですが、/-1/ と /-2/ があった行数を記憶して、後から 行の番号を比較してどうにか区切ろうと思ったのですが、やっぱり最初は$barcode22=0だし、全然駄目です。 普通、どのようにするのか教えて頂けませんか? よろしくお願いします。 sub read_file_to_array { my($file)=$filename; open (FILE, "<$dir\\$database\\Defect\\$file") or die "Can't open $file\n"; $line=0; while (<FILE>){ if ($_ =~ /-1/) {$barcode11=$.}; if ($_ =~ /-2/) {$barcode22=$.}; if ($line > $barcode22) {print "$_ ";}#試しにSTDOU#に出力してみるだけ } $line++; } |
動くかわからんけどとりあえずできた sub read_file_to_array { #←? my $file = shift; open (FILE, "<$dir\\$database\\Defect\\$file") or die "Can't open $file\n"; open (OUT1, ">$dir\\$database\\Defect\\${file}_1") or die; open (OUT2, ">$dir\\$database\\Defect\\${file}_2") or die; my ($flag1, $flag2); while (<FILE>) { if ( /-1/ ) { $flag1 = 1; } if ( /-2/ ) { $flag2 = 1; $flag1 = 0; } if ($flag2) { print OUT2; next; } if ($flag1) { print OUT1; next; } } } |
うぎょぎょ。。if ($flag2) {〜の部分の順番が逆になっちゃってるし。ダサ・・ closeしてないし・・終了時に閉じられるから大丈夫かアハハ |
>>2251 ミング 必ずデータの先頭が .*-1 か .*-2 であるなら while (<FILE>) { if ( /-[12]/ ){ chomp; open (OUT, ">$dir\\$database\\Defect\\$_") or die; next; } print OUT; } かなぁと思うんですが、違うかな? 業務用プログラムかだとちゃんとエラーチェックしないとまずい でしょうが、データの内容がある程度保証されているなら、こんな テキトーな感じでよろしいかと思います。 |
ナナシサソさん、68userさん 出来ました!! ご指導どうもありがとうございました。 |
二日連続の質問になってしまいますが、よろしくお願いします。 No.2251のInput file名は"Ab00010", "Cd00020", のように文字と数字からなっているのですが、Outputは別のDirに"Ab00010" "Ab00011" "Cd00020" "Cd00021"というように、/-2/の部分は”元のファイル名+1”というファイル名にしたいのですが、、、、 800ページあるらくだの本も一応買ってきたのですが全然分からないので、ウェブサイトで調べてみたのですが、唯一これかな?と思ったのが: $string="abcd771gfds"; $string=~/(\W+)\s+(\d+)/; とすると、$1=abcd, $2=7771, $string=abcd771gfds になる、とあったんですが、 試してみると$1=" ", $2=" ", $string="4294967295"になってしまい、訳が分からなくなってきたのですが、これは全然違うアプローチなんでしょうか? どうしたら ”Ab00011”が作れるんでしょうか? |
$flag == 2 ? $string ++ : ; でいいと思う・・ゲロゲロ |
UNIXの歴史について、知ってる範囲で教えてください。 できれば、メールの方がありがたいです。 |
>>2257 ナナシサソ でもアルファベットと数字からなってるので、数字だと見てくれないみたいなんですけど、、、 |
>>2259 ミング Perlは妙なことが出来たり・・ 多分うまくいくと思うんだけどな・・ |
ミングさんはじめまして。 まず abcd771gfds の件です。 #!/usr/bin/perl $string = "abcd771gfds"; $string =~ /(\W+)\s+(\d+)/; print "1:<$1> 2:<$2> string:<$string>\n"; を動かすと 1:<> 2:<> string:<abcd771gfds> と出ました。 \W+ は、英数字(word)以外1文字以上なので、なくてあたりまえ。 \s+ は、空白文字(space)1文字以上なので、なくてあたりまえ。 \d+ は、数字(digit)1文字以上だが、前に \W も \s もないのでダメ。 もし、$1 に abcd、$2 に 771(7771 は間違い?)を入れようとするなら、 $string =~ /^([a-zA-Z])(\d+)/; とかでしょうか。 ^ は文字列の先頭を示します。 これをやらないとどこからサーチしはじめるかわからん。 [a-zA-Z] は英字。\d は数字。 (わー、目からウロコ。英字のカンタンな文字クラスってないんですね) #!/usr/local/bin/perl $string = "abcd771gfds"; $string =~ /^([a-zA-Z]+)(\d+)/; print "1:<$1> 2:<$2> string:<$string>\n"; を動かすと 1:<abcd> 2:<771> string:<abcd771gfds> となりました。 |
ミングさん、つぎにファイル名生成の件です。 もっとカッコいいプログラムはいくらでもあるかと思うんですが、 ここではわかりやすく確実に動くのを取りました。 #!/usr/bin/perl $fname = "Ab00010"; $fname =~ /([a-zA-Z]+)(\d+)/; $fname_a = $1; # 英字部分 $fname_n = $2; # 数字部分 $fname_n++; # 数字部分に1加算 $fname_n = sprintf "%05d", $fname_n; # 先頭にゼロを詰めて5文字に $fname = $fname_a.$fname_n; print "fname: $fname\n"; $fname_n++; # 数字部分に1加算 $fname_n = sprintf "%05d", $fname_n; # 先頭にゼロを詰めて5文字に $fname = $fname_a.$fname_n; print "fname: $fname\n"; $fname_n++; # 数字部分に1加算 $fname_n = sprintf "%05d", $fname_n; # 先頭にゼロを詰めて5文字に $fname = $fname_a.$fname_n; print "fname: $fname\n"; 実行してみます。 fname: Ab00011 fname: Ab00012 fname: Ab00013 ポイントは sprintf でしょうか。 これは文字列をいろんな形で整形しますが、汎用性が高すぎるので、 sprintf "%0n", m; n はケタ数、m は数字 で、m を n ケタ、ゼロ詰めで表示するとだけ今はご説明します。 ただですね、これだと1ファイルが10個以上のサブファイルに分けると Ab0002n に突入してしまって、 もし Ab00020 という元ファイルがあると名前が衝突しますが、 それはいいですか。 |
>>2258 オハツ > UNIXの歴史について、知ってる範囲で教えてください。 「UNIXの1/4世紀」 http://www.ascii.co.jp/books/detail/4-7561/4-7561-3659-1.html を読みましょう。 |
ふくしさん、ナナシサソさん、 ご教授どうもありがとうがざいました。 やっと出来ました。 とても分かり易く助かりました。 今後もいろいろと宜しくお願いいたします! |
はじめまして。教えていただきたいことがあります。 こちらを参考に、perlのネットワークプログラムを作りたいと思っています。OSはPlamo Linux、perlは5.005です。 やりたいのはローカルネットワーク上に、ブロードキャストでメッセージを送って、ポートを開いている全部のコンピュータがそのメッセージを受信するというものです。 試験として #!/usr/local/bin/perl use IO::Socket; $socket = IO::Socket::INET->new( PeerAddr => '192.168.0.255', PeerPort => 2425, Proto => 'udp', ); if ( ! $socket ){ die "接続できませんでした。 $!\n"; } print $socket "test"; $socket->flush(); $socket->close(); と、いうのを動かしてみました。ブロードキャストである192.168.0.255ですから、2425でポートを開いている他のPC(VBのwinsockを使いました)にtestが表示されるかと思ったのですが、 > 接続できませんでした。 不正なファイルデスクリプタです というエラーが返って来てしまいます。 このエラー、192.268.0.3の様にIPを指定すると、出現しません。 いろいろとサーチエンジンなどもあたったのですが、どうしてもこの原因がつかめず、困っています。 perlを使って、udpとブロードキャストアドレスでネットワーク通信されている方がいらしたら、ブロードキャストアドレスをどうやって指定しているか、教えていただけませんでしょうか? よろしくお願いいたします。 |
>>2265 武田一浩 broadcast するときは、socket option の設定 $socket->setsockopt(SOL_SOCKET, SO_BROADCAST, 1) || die "$!"; が必要です。 IO::Socket じゃなくて普通の Socket モジュールを使うなら setsockopt($socket, SOL_SOCKET, SO_BROADCAST, 1) || die "$!"; ですね (これは IO::Socket で生成したソケットに対しても有効です)。 ただ、こちらで試した限りでは、 > 接続できませんでした。 不正なファイルデスクリプタです というエラーは出ませんでした。if ( ! $socket ) でエラー になっているということは、何か別の原因があるような気がします。 ちなみに printf $socket "1:%d:name:hostname:%d:ext\0group", time(), 0x1; で参加通知です。 |
No. 2266 # 68user さん、リプライありがとうございます。 次の様に修正してみました。 #!/usr/local/bin/perl use IO::Socket; $socket = IO::Socket::INET->new( PeerAddr => '192.168.0.255', PeerPort => 2425, Proto => 'udp', ); $socket->setsockopt(SOL_SOCKET, SO_BROADCAST, 1) || die "$!"; if ( ! $socket ){ die "接続できませんでした。 $!\n"; } printf $socket "test"; $socket->close(); 結果は、 Can't call method "setsockopt" on an undefined value at ./udptest.pl line 11. でやはり駄目でした。 192.168.0.255のアドレスを、特定のPCのIPに設定すると、そのPCにはtestの表示が出ますから、スクリプトそのものにはエラーがないのだと思いますが、なぜか私の環境ではブロードキャストアドレスが使用できない(?)のではないかと思います。 とりあえず、Perlやスクリプトには異常がなさそうなので、Plamo Linux のMLにでも質問をあげてみることにします。 ありがとうございました。 |
・・ <% strPathName = "HTTP://××/××/××/○○○.xls %> <a href=<% =strPathName%> ><% = strData(cnt)(0)%></a> ・・ </html> 上記のようにリンクしたいパス名を設定しました。 やりたいことは、 既存のダイアログ『ファイルのダウンロード画面 次の場所からファイルをダウンロードするように選択しました』 を表示させてからExcelを表示したいのですがどうしたらいいですか? 現象として、 すぐにExcelが表示されてしまいます。 |
はじめまして、どうしても分からない事があるので質問させて下さい。 HTMLの中にSSIでCGIのファイルを読み込ませようとしたのですが <!--#include file="test.cgi" --> だとOKなのですが <!--#include file="test.cgi?id=kouji" --> のように引数を付けると [an error occurred while processing this directive] とエラーになってしまいます。 「?」の部分からエラーが表示されるのですが、これを回避する方法を教えて下さい。 webも調べてみたのですが、結局分かりませんでした。 http://tohoho.wakusei.ne.jp/wwwssi.htm こちらの下の方に書いてあるexecの例で >○ <!--#exec cgi="xx.cgi"--> >× <!--#exec cgi="xx.cgi arg1 arg2"--> >× <!--#exec cgi="xx.cgi?arg1+arg2"--> >× <!--#exec cmd="xxx.pl"--> >○ <!--#exec cmd="/bin/xxx arg1 arg2"--> >○ <!--#exec cmd="./xxx.pl arg1 arg2"--> これの○で書いてあることみたいに引数を渡そうとしても駄目でした・・・ よろしくおねがいします。 |
なんでも聞いてすいません。 Windows 2000 以降についてくる「メモ帳」の「名前をつけて保存」では、 ISO-2022-jp および Shift_JIS(正確には Windows 932 および Windows 1152)のことを 「ANSI」と呼び習わしていますが、これはどういう経緯でしょうか? ANSI といえばアメリカの工業規格で、ASCII や ISO-8859-1 を規定してるもんだと 思い込んで生きてきましたが、Delphi の入門本とか ML とかを見ても 「ANSI 文字列を Unicode に変換、、」とかいって、 Windows で使える Unicode 以外の文字、という意味で ANSI 文字列、 と書いてあるようなんですが、この言葉は正しい業界用語なんでしょうか? それとも Windows ローカル語? この言葉のスコープはどこまでなんでしょうか? 「メモ帳」といえば UTF-16LE-BOM のことを「Unicode」、 UTF-16BE-BOM のことを「Unicode Big Endian」、UTF-8 のことを「UTF-8」と言ってますが、 これなんかも業界用語なのか Windows 語なのか単なるメモ帳の開発者の気の迷いなのか わかりません。(あ、でも Word も共通なんだよな、、) 場違いでしたら情報のポインタや、討議するのにふさわしい掲示板等教えてください。 よろしくお願いいたします。 |
とても素人で、申し訳ないのですが、ご存知の方がいらしたら、教えて下さい。ハードは、IBM社のRS/6000を使用しています。kシェルを作成して下記の作業を行いたいと考えています。 複数のテ゛ィレクトリーに10〜30のファイルが存在しています。 各ファイル中に/usr/kokyakuと記述があれば、/usr/okyaku と変更したいと考えています。sedコマンドを利用すればそれぞれのファイルの中身を変更させることは可能であることは、分かったのですが、対象の ファイル数が多い為、該当のディレクトリーにcdし、 grep -l'/usr/kokyaku' * > filename などで、対象ファイル名を保存したファイルを作成し、そのファイルを自動的に読み込んでファイル名をいちいち指定せずにsedコマンドを実行でき ないものでしょうか?awkコマンドでファイル名が保存されているファイルを読み込み、sedコマンドの出力ファイルを$1の名前にするなどは可能なのでしょうか? ちなみに、イメーシ゛的には、カレントディレクトリーの下のファイル(*)の内容を自動的に置換してほしいのですが… sed 's/\/usr\/kokyaku/\/usr\/okyaku/g' * >*の出力 つたない説明で、申し訳ありませんが、お知恵を頂けたらありがたいです。 |
みーさん: Perl ですいません、一応テストもしました。 ミソは find コマンドの出力を ` ` で配列に入れて for で処理している、、(フツーやんねえかな、、) #! /usr/local/bin/perl -w # kokyakuokyaku $tmp = "TempFileDayooon"; # 中間ファイル。存在しないファイル名を選ぶこと for $file (`find . -print`) { chomp; if (-f $file) { open FILE, $file; open TMP, ">$tmp"; while (<FILE>) { s|/srv/kokyaku/|/srv/okyaku/|g; print TMP; } close TMP; close FILE; rename $tmp, $file; } } |
(一応)ふつー File::Find 使うよね。知ってるー (^^;;; |
ふくしさんどーもありがとうございました。大変申し訳ないのですが、findコマンドの使い方をよく理解していないので、どなたかお教え頂けないでしょうか?私の理解としては、ディレクトリー内の条件にあったファイルを探す時に使うコマンドだと思っていたので、例えば、頭に’m*’がつくファイルを探したりする時に使用するものだと思っていました。1つあるいは複数のファイルから、指定パターンに合致した行を探しその対象のファイル名を表示させる為には、grepしか使用出来ないと思っていたのですが、findコマンドで、ファイル(シェル)中に/usr/kokyakuと記述されているファイル名をfindコマンドで探す場合は、どのように記述すればよいのでしょうか? また、ふくしさんの記述して下さった各行の処理内容をもう少し詳細に教えて頂けないでしょうか?お手数をおかけいたしますが、よろしくお願いいたします。 |
>>2267 武田 一浩 $socket = IO::Socket::INET->new( PeerAddr => '192.168.0.255', PeerPort => 2425, Proto => 'udp', ) || die "$!"; とした方が、どこでエラーが出ているかを把握しやすいでしょう。 > とりあえず、Perlやスクリプトには異常がなさそうなので、 そうですね。perl か OS の問題ではないかと思います。 あと、ifconfig -a して、デバイスに fxp0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500 と、「BROADCAST」が付いていてブロードキャストに対応していることを 確認して下さい。もしかして ppp デバイスだったりすると付いてないかも。 >>2268 もみの木 > 現象として、すぐにExcelが表示されてしまいます。 要は、ASP は全く関係なくて <a href="HTTP://××/××/××/○○○.xls">hoge</a> というリンクをクリックしたときの挙動ですよね? Windows は よくわからないので、 http://www.parkcity.ne.jp/~chaichan/bin/qanda.cgi?modefg=9 で質問した方がよろしいと思います。 あとの話題は後ほど。 |
みーさん: なんかすいません。 たぶんぼくのやり方すごく非標準的なので、 もっとカッコいい方法はいくらでもあると思うんですが、、 find はファイル名の検索、 grep はファイルの中の文字列の検索、 で、合ってます。 ぼくのスクリプトでは各ファイルの中での文字列検索/置換を 自分で書いています。(while のあたり) #! /usr/local/bin/perl -w # kokyakuokyaku $tmp = "TempFileDayooon"; # 中間ファイル。存在しないファイル名を選ぶこと for $file (`find . -print`) { chomp $file; # すいません、ココ、間違ってました if (-f $file) { open FILE, $file; open TMP, ">$tmp"; while (<FILE>) { s|/srv/kokyaku/|/srv/okyaku/|g; print TMP; } close TMP; close FILE; rename $tmp, $file; } } `UNIXコマンド` …バッククォート(`)でUNIXのコマンドを囲むと、 出力結果をリストで返す for $変数 (リスト) { ...なんだかんだ... } …リストの要素を1個ずつ $変数 に入れながら、 「なんだかんだ」の部分を繰り返す。 上では find の結果を1行ずつ $file に入れて処理している。 それはカレント ディレクトリ以降のファイル/ディレクトリである。 % find . -print …カレント ディレクトリ以降のファイル/ディレクトリを一覧表示する。 chomp $file; …$file(find の結果の1行)の末尾から改行を取り除いて、 ファイル/ディレクトリ名として正しいものにしている -f 文字列 …「-f」はファイルテスト演算子のひとつ。 右に来る文字列がふつうのファイルだったら真を返す。 ここではディレクトリをはじいている。 open FILE, $file; …ファイル名 $file のファイルを入力で開いて、 ファイルハンドル FILE で入力アクセスできるようにする open TMP, ">$tmp"; …ファイル名 $tmp のファイルを出力で開いて、 ファイルハンドル TMP で出力アクセスできるようにする while (<FILE>) { ...なんだかんだ... } …ファイルハンドル FILE で読み込まれる ファイル $file(ここでは find の結果のうち、ファイルのみ)の 1行1行を、$_ という特殊な変数に入れながら 「なんだかんだ」の部分を繰り返す。 $file を読み終わったらループを脱出する s|/srv/kokyaku/|/srv/okyaku/|g; …デフォルトの作用対象である変数 $_ に対して、 「/srv/kokyaku/」を「/srv/okyaku/」に置換する。 s は substitute(置換)、g は global(全体的に)の略。 g を略すと1行に1回しか置換しない print TMP; …TMP ファイルハンドルに、デフォルトの作用対象 $_ を出力する ここで $_ は FILE の1行1行に 「/srv/kokyaku/」=>「/srv/okyaku/」の置換を施したものである close TMP; close FILE; …ファイルを「閉じる」。 (ファイルアクセスのために確保されていたメモリなどの資源を解放する) rename $tmp, $file; …置換する前のファイル名が $file、 置換したあとのファイル名が $tmp なので、 $tmp を $file に改名する。 これで置換したファイルで元ファイルは上書きされ、 中間ファイル TempFileDayooon は消えてなくなる こんな感じでしょうか。 |
>>2271 初心者みーです。 複数ファイルの中身を一括置換する、という目的に限れば、 http://x68000.startshop.co.jp/~68user/unix/pickup?perl の perl -pi.bak -e .. ところをどうぞ。 > findコマンドで、ファイル(シェル)中に/usr/kokyakuと > 記述されているファイル名をfindコマンドで探す場合は、 > どのように記述すればよいのでしょうか? いろいろありますが、以下のような感じです。 % find . -exec grep -l /usr/kokyaku {} \; … 機能は実現できるけど、遅い。 % grep -l * … ファイル数が多すぎるとダメ。ファイル数が数千程度ならこれでいいでしょう。 % find . -print | xargs grep -l … ファイル数が多くても OK。 % find . -print0 | xargs -0 grep -l … ファイル数が多くても OK。ファイル名に改行が含まれていても OK。 今回は grep -l でいいのではないでしょうか。 あと、 > sed 's/\/usr\/kokyaku/\/usr\/okyaku/g' * >*の出力 で実現できることはわかっているので、後はこれを複数のファイルに対して実 行すればよいのです。いろいろ方法はありますが、お勧めなのは「文字列をい じくってコマンドラインを作り、sh に喰わせる」方法です。 grep -l * で、 file1 file2 file3 という出力が得られるとします。次に grep -l * | sed "s|\(.*\)|sed 's./usr/kokyaku./usr/okyaku/.g' < \1 > out/\1 | " とすると、 sed 's./usr/kokyaku./usr/okyaku/.g' < ./file1 > out/./file1 sed 's./usr/kokyaku./usr/okyaku/.g' < ./file2 > out/./file2 sed 's./usr/kokyaku./usr/okyaku/.g' < ./file3 > out/./file3 という文字列が得られます。それをよく確認して、よさそうなら grep -l * | sed "s|\(.*\)|sed 's./usr/kokyaku./usr/okyaku/.g' < \1 > out/\1 | " | sh と末尾に | sh を付ければ、そのまま実行されます。 正しいコマンドラインができるまでは「| sh」を付けずに試行錯誤すれば よいので、いろいろなところで応用が効くと思います。 |
>>2270 ふくし > 場違いでしたら情報のポインタや、討議するのにふさわしい > 掲示板等教えてください。 場違いではないですが、わかりません。会社では Windows Me だし (笑) ふさわしいところは… fj.kanji くらいしか思い付かないなぁ…。 後は >>2269 kouji ですが、これはちょっと調べてから回答したいと思います。 |
ふくしさん、68userさんどうもいろいろありがとうございました。とっても勉強になりましたし、助かりました。perl -pi.bakの方法で、一括変換変換させる方法をバックアップファイルも一緒に作成できるので、実施したいと思います。簡単なテストをしたところ、大丈夫そうでしたので…。他の方法も、今後時間のある時に試してみたいと思います。迅速なご回答と親切な説明、本当にありがとうございました。 |
始めましてm(__)m UNIXを学校で使っています。 家では使えないんでしょうか? 家にパソコンはあるのですが…(-.-;) |