2010-07-02 3 views
1

사이트를 열고 Hail Reports라는 단어를 검색하고 다시 정보를 제공하는 작은 perl 프로그램을 작성하고 있습니다. 필자는 perl에 익숙하지 않기 때문에이 중 일부는 간단하게 수정할 수 있습니다. 처음에 제 코드는 제가 unitialized 값을 사용하고 있다고 말합니다. 여기에 내가perl HTML 구문 분석에 대한 약간의 도움

#!/usr/bin/perl -w 
use LWP::Simple; 

my $html = get("http://www.spc.noaa.gov/climo/reports/last3hours.html") 
    or die "Could not fetch NWS page."; 
$html =~ m{Hail Reports} || die; 
my $hail = $1; 
print "$hail\n"; 

이 두 번째로, 나는 정규 표현식 내가 원하는 일을 할 수있는 가장 쉬운 방법이 될 것이라고 생각 무엇을 가지고,하지만 난 그들과 함께 그것을 할 수 있는지 모르겠습니다. 내 프로그램에서 Hail Reports라는 단어를 검색하고 Hails Reports와 Wind Reports라는 단어 사이의 정보를 다시 보내주기를 바랍니다. 정규 표현식을 사용할 수 있습니까? 아니면 다른 방법을 사용해야합니까? 다음은 내가 당신의 정규식 중 어느 것도 괄호 안에 없었다 때문에 $ 1에 다시

 <tr><th colspan="8">Hail Reports (<a href="last3hours_hail.csv">CSV</a>)&nbsp;(<a href="last3hours_raw_hail.csv">Raw Hail CSV</a>)(<a href="/faq/#6.10">?</a>)</th></tr> 

#The Data here will change throughout the day so normally there will be more info. 
     <tr><td colspan="8" class="highlight" align="center">No reports received</td></tr> 
     <tr><th colspan="8">Wind Reports (<a href="last3hours_wind.csv">CSV</a>)&nbsp;(<a href="last3hours_raw_wind.csv">Raw Wind CSV</a>)(<a href="/faq/#6.10">?</a>)</th></tr> 
+0

XPath를 사용하여 이것을 시도 할 수 있습니까? –

답변

2

당신은 캡처 된 아무것도 보내지하려는 웹 페이지 소스 코드의 조각이다. 다음은 나를 위해 일한다.

#!/usr/bin/perl 
use strict; 
use warnings; 

use LWP::Simple; 

my $html = get("http://www.spc.noaa.gov/climo/reports/last3hours.html") 
    or die "Could not fetch NWS page."; 

$html =~ m{Hail Reports(.*)Wind Reports}s || die; #Parentheses indicate capture group 
my $hail = $1; # $1 contains whatever matched in the (.*) part of above regex 
print "$hail\n"; 
+0

두 가지 문제를 모두 해결해 주셔서 감사합니다. – shinjuo

1

정규식의 괄호 캡처 문자열입니다. 정규식에 괄호가 없으므로 $ 1이 (가) 설정되지 않았습니다. 당신이 한 경우는 $ html로 변수에 존재하는 경우

$html =~ m{(Hail Reports)} || die; 

는 다음 $ 1이 "우박 보고서"로 설정 될 것이다. 당신은 단지이 일치하는 경우 알고 싶어하기 때문에, 당신은 정말이 시점에서 무엇을 캡처 할 필요가 없습니다 당신은 쓸 수 뭔가 같은 :

unless ($html =~ /Hail Reports/) { 
    die "No Hail Reports in HTML"; 
} 

은 당신이 좋아하는 일을 할 수있는 문자열 사이에 뭔가를 캡처하려면 :

if ($html =~ /(?<=Hail Reports)(.*?)(?=Wind Reports)/s) { 
    print "Got $1\n"; 
} 
+0

당신은 정규식에서 개행을 가로 질러 일치하도록 's'수정자를 필요로합니다. 즉, ~ ~ /.../s –

+0

고마워요. 업데이트되었습니다. – runrig

3

초기화되지 않은 경고는 $ 1에서 발생합니다. 아무 곳에서나 정의되거나 설정되지 않았습니다. "사이"라인 레벨 대신 바이트 수준에 대한

당신은 사용할 수 있습니다

for (split(/\n/, $html)) { 
    print if (/Hail Reports/ .. /Wind Reports/ and !/(?:Hail|Wind) Reports/); 
} 
3

단일 및 멀티 라인 일치를 사용합니다. 또한 텍스트 사이의 첫 번째 일치를 선택하기 만하므로 욕심을 느끼는 것보다 조금 더 빠릅니다.

#!/usr/bin/perl -w 

use strict; 
use LWP::Simple; 

    sub main{ 
     my $html = get("http://www.spc.noaa.gov/climo/reports/last3hours.html") 
       or die "Could not fetch NWS page."; 

     # match single and multiple lines + not greedy 
     my ($hail, $between, $wind) = $html =~ m/(Hail Reports)(.*?)(Wind Reports)/sm 
       or die "No Hail/Wind Reports"; 

     print qq{ 
       Hail:   $hail 
       Wind:   $wind 
       Between Text: $between 
      }; 
    } 

    main(); 
관련 문제