Perlについての質問箱 2箱目

このエントリーをはてなブックマークに追加
>950の頭がな。
while()の使い方勉強し直したほうがよさげ。
>>950
板違い
>>950
while判定式の真偽の意味をキチンと理解してないからだろうなぁ…。
そのコードでは、ループは一度も実行されないのが正しいぞ?w

希望するループの脱出条件は「20になったら」であるから──

$random = 0; # <-- ゼロ初期化されている=20では“ない”
while ( $random != 20 ) { # <-- 20では“ない”時はループせよ

または、

until ( $random == 20 ) { # until=while とは真偽判定が逆の命令
インターネット上のファイル(.html)が存在するかどうか
インターネット上のファイルのオープン

で困っています。if(-e $URL)やopen(FILE,$URL)でいいんですか?
956デフォルトの名無しさん:02/12/27 21:16
そろそろ正月だし、おめでたいなぁ
>>955
それではムソ。いくつか方法はあるんだが…、

1.CPANでその種のモジュールを探してきてインストールする(具体名忘れた、スマソ)
2.(UNIXでなら外部コマンドの) wget などを利用して読み込む

open FILE, "wget $URL|" or die;
binmode FILE;
$data = join '', <FILE>; close FILE; # (エラー処理やタイムアウトは知らん)

3.自力で低レベルコーディングするw

この辺がサンプルになるとオモワレ。
ソース?: ttp://multix.jp/download/perl/httpget.cgi
実行例?: ttp://multix.jp/cgi-bin/httpget.cgi
959 ◆hMJAPH9PWA :02/12/28 09:27
>>899
perl5.8.0は以前のバージョンとバイナリ互換がないので、
XSを使ったモジュールは5.8.0用にビルドされたものじゃないと動かないよ。
それが5.8.0に対応するのを待つか、他のを探すか、自分でビルドするしかないね。
960950:02/12/28 13:00
>>954
恥ずかしい。すごく簡単なことだったんですね。
あんな簡単な事も丁寧に教えてくださってありがとうございます。
とても参考になりました。
>>958
ありがとう。HTMLなんだけど、やっぱりバイナリとして開いたほうがいいのかなぁ。
use LWP::Simple;

my $url = 'http://pc3.2ch.net/test/read.cgi/tech/1033688230/l50';
my $text = get $url;
$text =~ s/<br>/\n/ig;
$text =~ s/<dd>/\n/ig;
$text=~ s/<.*?>//sg;
$text=~ s/</</g;
$text=~ s/>/>/g;
print $text;
exit;
963デフォルトの名無しさん:02/12/28 18:35
955さんではないのですが、似たようなプログラムで悩んでいます。
htmlを取ってきた後、そこに含まれるURLを取り出してリスト(txtとか)に
するにはどうしたらいいでしょう。
更にはそのリストを使ってたくさんのサイトを巡ってプレーンテキストを
収集するプログラムが作りたいのですが・・。
根本的にチグハグな>>961がいるスレはここですか?
965デフォルトの名無しさん:02/12/28 19:08
>>822 みたいに fork を使いたいのですが、 >>822 のままだと
1秒毎にゾンビプロセスが残ります。
fork の最後に exit してるのに何故でしょう?
>>964
うん…。萎えるよねぇ。

>>963
とりあえずHTMLを取ってくる方法は>>958>>962
参考にしていただくとして、例をあげると、

$/ = undef; # (次の行のための細工)
$_ = <>; # 仮に標準入力からHTMLテキストを頂くとして
s/\s+/ /g; # 邪魔な改行や連続空白を整理
s{(src|href)\s*=\s*"?([^"]+)"?}{ # それっぽい所を抜き出す
push @urllist, $2; "";
}eg;
print "$_\n" foreach (@urllist); # 標準出力へ書き出す

注:相対URLの絶対アドレス化までは面倒見てないし、
空白を含むような変態アドレス(爆)にも対応してないし、
リンクタグになってないURLも無視している。

あとはこの処理結果を更に再帰的にやってみる?(無限ループしそうだが)

>>965
waitpid 関数のドキュメントも参照してみたらどうだろう?
967963:02/12/28 20:04
>>966
標準入力から渡したのはちゃんと抽出できました。
この$_ = <>;をソケット先の読み込んだのにしてあげれば良いのですね。
試行錯誤してみます。
組み始めて1ヶ月くらいなので解からないことばかりで^^;
ありがとうございます><
use LWP::Simple;
use HTML::LinkExtor;

my $url = 'http://www.google.com/intl/ja/';
my $p = new HTML::LinkExtor(\&want, $url );
$p->parse(get $url or die "filed:get $url");
exit;

sub want
{
my($tag, %links) = @_;
$tag = lc $tag;
return unless $tag eq 'img';
print $links{ src }, "\n";

}
<Table></table>の中に<table></table>といくつか入っているのですが、
そと側の<table.にマッチさせるにはどうしたらいいdねすか?

「<table>の開始タグと終了タグを一致させたい」みたいな
970963:02/12/28 22:01
>>968
すごい。。相対的なURLもこれだけでOKなんですね。
末尾に/がないものや.cgi等も持ってきちゃう場合は
削除や書き込まないようにすればいいのでしょうか。
>>970
ちょこっとでいいからソケットプログラミングやってみると良いと思われ。
便利なライブラリを使うとすぐできちゃうけど、
それだと基本が身につかないから応用ができないよ。
972デフォルトの名無しさん:02/12/28 23:24
>>971
始めてから1箇月でこの程度の才能無しにアドバイスしても
無駄だと。
そんな程度でageるやつもどうかと。
974デフォルトの名無しさん:02/12/29 20:27
Net::SCP 使ってファイル転送したいのですが、認証がうまくいかないようです。
RSA1? RSA2? どれを使えばいいのでしょうか?
検索してみても有効な結果が見つかりませんが、perldoc以外のサンプルコードありませんか?
975デフォルトの名無しさん:02/12/29 22:15
<a href="ここ">ここ</a>(ここ)
上の「ここ」の部分を取得したいのですが、色々な例外を考えて
いくとどうも上手くマッチさせることができません。
考えなくてはならないことは
・タグの中には余計な要素があるかもしれない
・最後の要素と閉じタグの間には文字があるかもしれない
・最後の要素はないかもしれない

これを考えていき(\nはないものとして)
/<.*?a.+?href=\"(.+?)\".*?>(.+?)<\/.*?a.*?>.*?(\(.+?\))?/ig
としてみたのですが、最後の要素と閉じタグの間に文字があると
例えあっても、最後の要素がないことになってしまいます。

この場合にはどのようにするのが適当でしょうか?
何でも . を使うな。
977 ◆F52DmOxJlc :02/12/29 22:28
>>975
/<.*?a.+?href=\"(.+?)\".*?>(.+?)<\/.*?a.*?>[^(]*(\(.+?\))?/ig
これでどうだ?
.*? を [^(]* に変更。
( 以外の何かの0回以上の繰り返し。
978977:02/12/29 23:08
>>976 >>977
ご指摘ありがとうございます。 . で表しすぎているということに
気付きました。
> /<.*?a.+?href=\"(.+?)\".*?>(.+?)<\/.*?a.*?>[^(]*(\(.+?\))?/ig
これを試してみたのですが下の
<a href="xxx">xxx</a><a href="xxx">xxx</a>(xxx)
全体にマッチしてしまいます。上の文字列に対しては
2回マッチするようにしたいのですが、
少し考えてイメージとしてはこんな感じなのですが
/<[^>]*?a[^>]+?href=\"([^\"]+?)\"[^>]*>(.+?)<\/[^>]*?a[^>]*?>[^(?:<a)]*?(\([^)]+?\))?/i
[^(?:<a)]←この <a という文字列以外にマッチという部分が
実際は上手く表せません。
何か良い手はないものでしょうか。
979975:02/12/29 23:09
>>978 の名前を間違えて977にしてしまいました
.*?ってさ、.*とどう違うの?何か違うのか?素人考えでスマンが。

<[^>]?a だと <!DOCTYPE html PUBLIC (略) Tradi...のaなんかにもマッチしてしまわないか?
<a で良いと思うんだけど。

あと、hrefの値に"があると分かっているの?
場合によっては "が'になっているかもしれないし。
981975:02/12/30 00:00
/<[^>]*?a[^>]+?href=\"([^\">]+?)\"[^>]*?>(.+?)<\/[^>]*?a[^>]*?>(?:(?:<(?!a))|[^<])*?(\([^)]+?\))?/i
試行錯誤してこのような形になりました。これでも
</a>と(xxxxx)の間に文字があると失敗してしまい上手く取得することができません。

>>980
>.*?ってさ、.*とどう違うの?何か違うのか?素人考えでスマンが
<[^>]*a[^>]
のように書き始めてしまうと<a href="a.html">でa.htmlのaまで
マッチしてしまい、上手くいかないと思い<[^>]*?aで書き始めました。

><[^>]?a だと <!DOCTYPE html PUBLIC (略) Tradi...のaなんかにもマッチしてしまわないか?
これは hrefの段階でマッチが失敗するので大丈夫だと思います。

>場合によっては "が'になっているかもしれないし。
確かにその通りでした。("|')?のようにして上手くしのぎたいと思います。
982975:02/12/30 00:02
激しく嘘を書いていました。

>のように書き始めてしまうと<a href="a.html">でa.htmlのaまで
>マッチしてしまい、上手くいかないと思い<[^>]*?aで書き始めました。

これはまたhrefでマッチが失敗するので大丈夫ですね・・・
<a target="top" href="xxxxx">の場合にtargetのaにマッチしてしまうため
<[^>]*?a
として書き始めました。
983デフォルトの名無しさん:02/12/30 00:08
……むりに一発ですべて取得しなくても……
HTML/SGML/XML系タグパースは無茶苦茶難しい。
どこかで妥協しないと泥沼確定。正規表現は万能に近いが得手不得手はある。
#特に iso-jis や Shift_JISコードが混じってると余計に死ねるw

>>980
/.*?/ の?は最短マッチフラグ。普通“.*”は最長一致(貪欲マッチ)だが、
最初に検索条件を満足したところでストップ(break)をかけるために使う。

$_ = "1,2,3,";
print $&, "\n" if /.*,/; # 1,2,3, <- 最後まで全部当たってしまう
print $&, "\n" if /.*?,/; # 1, <- 最初に当たったところで止まる

このフラグはどんな量指定子にも使える。
?? +? *? {n}? {n,}? {n,m}? といった具合。(続に言うPerl拡張)

/<[^>]?a/ だけど、昔はともかく現在は
タグ開始を示す“<”の直後に空白や改行を入れるのは
イリーガルなはずなので、/<a/ で充分だろうなぁ。
逆にタグ内や“=”の前後、“>”直前の空白&改行挿入とかは許されるので
そういうのまで考えてくと本当にキリがない。
素直に既存のモジュールから使えそうなのを探したほうが楽よ。
#それでも「(>_<)」といった顔文字があると動作が狂いやすいが…。
985975:02/12/30 01:25
>>984
確かにこのままでは無理そうなので、妥協して
aタグ以外を取り払ってからマッチさせることにしました。

s/<\/[^a][^>]*>//ig;
s/<[^a\/][^>]*>//ig;
/<a\s*href=\"(.+?)\"[^>]*>(.+?)<\/a>\s*(\(.+?\))?/i;

特定のサイトのを取ることができればよかったので、
とりあえずは上手く動かすことができました。
986デフォルトの名無しさん:02/12/30 02:23
質問です。

「1〜36の数字があって、その中からランダム数字を選んでに10対のペアを作る。
 ただし、選ばれる数字(この場合には全20個)には同じ数字が含まれてはならない。
 (つまり一度選ばれた数字は2度と選ばれないということ。)」

さて、どうやったらいいですかねえ?
配列を使うということくらいしか思いつかない。
ちゃんと確かめてないし眠いしチャット中の相手の返事町の間に考えたものですが。
for ($i = 1; $i <= 10; $i++) {
$x = int(rand(36));
if (!$a{$x}) { $a{$x} = 'hoge'; }
}
@a = %a;
for ($i = 1; $i <= 10; $i++) {
$x = int(rand(36));
if (!$a{$x}) { $a{$x} = 'hoge'; print "$a[($i -1)*2]\t$x\n";}
}
988987:02/12/30 03:02
絶対動かないなこれ。スマソ
10満開ぐらい動かせば奇跡的にうまくいくかもしらんけど。
ttp://www.din.or.jp/~ohzaki/perl.htm#Mail
メールアドレスもまじめにやるとこんな感じになっちまうらしいしな。
990 ◆F52DmOxJlc :02/12/30 07:22
>>987
出勤前で時間がないので考え方だけ。
・配列に 1 - 36 を格納。
・int(rand(36)) で一つを決定。
・決定した数字を配列から消す。これで配列の要素が一つ減る。
・以下 int(rand(35)), int(rand(34)), int(rand(33)) ...

次スレ、
Perlについての質問箱 3箱目
http://pc3.2ch.net/test/read.cgi/tech/1041205885/l50
>>987
>>990を参考に作ってみた

srand;
@card = (1 .. 36);
$pair = 10;
@result = ();
for($i=0;$i<$pair; $i++){
 ($p1) = splice(@card,int(rand(@card)),1);
 ($p2) = splice(@card,int(rand(@card)),1);
 push(@result, [$p1,$p2]);
}

foreach $in (@result){
 print $in->[0], ":", $in->[1], "\n";
}

一時変数使わないようにしたり、リファレンス止めたり色々出来るけど
分かりやすい基本形って事で
>>984
最短マッチね。さんくす。

そーいや、Perlって「独自拡張」があるんだね。

#旧スレですまん
994986:02/12/31 02:37
>>987,990,992 (同一人物含む?)
さんくす。

> ・決定した数字を配列から消す。これで配列の要素が一つ減る。

の実現の仕方がよく分からなかったんだよなあ。
>>992のコードよく読んで勉強しまつ。
995992:02/12/31 05:10
>>994
$index = int(rand(@card));
($p1) = splice(@card,$index,1);
分けると分かりやすいかも
996
九百九十七
998 ◆F52DmOxJlc :02/12/31 20:06
ん?カウントアップか?
998
1000get.
1000?
10011001
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。