문자열에서 정규식 패턴이 일치하지 않습니까? /> 하지만 난하지

<input>이 패턴을 사용하여 “숨겨진”유형의 필드 를 일치 시키려고합니다 .

/<input type="hidden" name="([^"]*?)" value="([^"]*?)" />/

다음은 샘플 양식 데이터입니다.

<input type="hidden" name="SaveRequired" value="False" /><input type="hidden" name="__VIEWSTATE1" value="1H4sIAAtzrkX7QfL5VEGj6nGi+nP" /><input type="hidden" name="__VIEWSTATE2" value="0351118MK" /><input type="hidden" name="__VIEWSTATE3" value="ZVVV91yjY" /><input type="hidden" name="__VIEWSTATE0" value="3" /><input type="hidden" name="__VIEWSTATE" value="" /><input type="hidden" name="__VIEWSTATE" value="" />

하지만 난하지 있는지 생각 type, name그리고 value속성이 항상 같은 순서로 나타납니다. 는 IF type속성이 마지막으로 오는 내 패턴으로는 시작이기 때문에, 경기가 실패합니다.

질문 : 태그
의 속성 위치에 관계없이 패턴이 일치하도록 패턴을 변경하려면 어떻게해야 <input>합니까?

추신 : 그런데 정규식 을 테스트하기 위해 Adobe Air 기반 RegEx Desktop Tool 을 사용하고 있습니다.



답변

여기에있는 모든 대답과 달리 정규식을 수행하려는 것은 완벽하게 유효한 솔루션입니다. 균형 잡힌 태그와 일치하지 않기 때문에 정규식으로는 불가능합니다! 그러나 하나의 태그에만 일치하며 완벽하게 규칙적입니다.

그래도 문제가 있습니다. 하나의 정규 표현식으로 할 수는 없습니다 … <input>태그 를 캡처하려면 한 번의 일치를 수행 한 다음 추가 처리를 수행해야합니다. 이것은 속성 값에 >문자 가없는 경우에만 작동 하므로 완벽하지는 않지만 정상적인 입력에는 충분합니다.

다음은 내가 의미하는 바를 보여주는 Perl (의사) 코드입니다.

my $html = readLargeInputFile();

my @input_tags = $html =~ m/
    (
        <input                      # Starts with "<input"
        (?=[^>]*?type="hidden")     # Use lookahead to make sure that type="hidden"
        [^>]+                       # Grab the rest of the tag...
        \/>                         # ...except for the />, which is grabbed here
    )/xgm;

# Now each member of @input_tags is something like <input type="hidden" name="SaveRequired" value="False" />

foreach my $input_tag (@input_tags)
{
  my $hash_ref = {};
  # Now extract each of the fields one at a time.

  ($hash_ref->{"name"}) = $input_tag =~ /name="([^"]*)"/;
  ($hash_ref->{"value"}) = $input_tag =~ /value="([^"]*)"/;

  # Put $hash_ref in a list or something, or otherwise process it
}

기본 원리는 하나의 정규 표현식으로 너무 많은 것을 시도하지 마십시오. 알다시피, 정규 표현식은 일정한 양의 주문을 시행합니다. 따라서 대신 추출하려는 대상의 컨텍스트와 일치시킨 다음 원하는 데이터에서 하위 일치를 수행해야합니다.

편집 : 그러나, 나는 일반적으로 HTML 파서를 사용하는 것이 더 쉽고 더 좋으며 코드를 다시 디자인하거나 목표를 다시 검사하는 것을 고려해야한다고 동의합니다. 🙂 그러나이 답변을 HTML의 하위 집합을 파싱하는 것은 불가능하다는 슬픔의 반응에 대한 반론으로 게시해야했습니다. 전체 사양을 고려할 때 HTML과 XML은 모두 불규칙하지만 태그의 사양은 상당히 규칙적입니다. 확실히 PCRE의 힘 안에서.


답변

오 예 당신은 정규 표현식을 사용하여 HTML을 파싱 할 수 있습니다 !

시도중인 작업에 대해 정규 표현식은 완벽하게 좋습니다 !

이다 대부분의 사람들이 정규 표현식 구문 분석 HTML의 어려움을 과소 평가하기 때문에 너무 가난 할 것이 사실.

그러나 이것은 계산 이론과 관련된 근본적인 결함이 아닙니다. 그 어리 석음이 여기 주변에 많이 파묻혀 있지만 믿지 마십시오.

그것은 확실하게 할 수있는 반면 그래서 (본 게시물이 논쟁의 여지가 사실의 존재 증명의 역할), 즉 의미하지 않는다  해야  합니다.

정규 표현식에서 전용의 특수 목적 HTML 파서에 얼마를 쓰는지 결정해야합니다. 대부분의 사람들은 그렇지 않습니다.

그러나 나는 생각합니다. ☻


일반 정규식 기반 HTML 파싱 솔루션

먼저 임의의 HTML을 정규식 으로 구문 분석하는 것이 얼마나 쉬운 지 보여 드리겠습니다 . 전체 프로그램은이 게시물의 끝에 있지만 파서의 핵심은 다음과 같습니다.

for (;;) {
  given ($html) {
    last                    when (pos || 0) >= length;
    printf "\@%d=",              (pos || 0);
    print  "doctype "   when / \G (?&doctype)  $RX_SUBS  /xgc;
    print  "cdata "     when / \G (?&cdata)    $RX_SUBS  /xgc;
    print  "xml "       when / \G (?&xml)      $RX_SUBS  /xgc;
    print  "xhook "     when / \G (?&xhook)    $RX_SUBS  /xgc;
    print  "script "    when / \G (?&script)   $RX_SUBS  /xgc;
    print  "style "     when / \G (?&style)    $RX_SUBS  /xgc;
    print  "comment "   when / \G (?&comment)  $RX_SUBS  /xgc;
    print  "tag "       when / \G (?&tag)      $RX_SUBS  /xgc;
    print  "untag "     when / \G (?&untag)    $RX_SUBS  /xgc;
    print  "nasty "     when / \G (?&nasty)    $RX_SUBS  /xgc;
    print  "text "      when / \G (?&nontag)   $RX_SUBS  /xgc;
    default {
      die "UNCLASSIFIED: " .
        substr($_, pos || 0, (length > 65) ? 65 : length);
    }
  }
}

얼마나 쉬운 지보십시오 보십니까?

작성된대로 각 HTML을 식별하고 해당 부분을 찾은 위치를 알려줍니다. 주어진 유형의 조각으로 또는 다른 것보다 더 특정한 유형으로 원하는 다른 작업을 수행하도록 쉽게 수정할 수 있습니다.

나는 실패한 테스트 사례가 없다 (왼쪽 🙂 : 100,000 개가 넘는 HTML 파일에서이 코드를 성공적으로 실행했다. 그 외에도, 특별히 구성된 파일에서 실행했습니다. 순진한 파서를 깨뜨리기 위해 .

이것은 아닙니다 순진한 파서 .

오, 나는 그것이 완벽하지 않다고 확신하지만, 아직 그것을 깨뜨리지 못했습니다. 나는 무언가가 있었더라도 프로그램의 명확한 구조 때문에 수정이 쉽게 적용 될 수 있다고 생각합니다. 정규 표현식이 많은 프로그램조차도 구조가 있어야합니다.

이제 그 길을 벗어 났으므로 OP의 질문에 대해 설명하겠습니다.

정규식을 사용하여 OP 작업 해결 데모

html_input_rx아래에 포함 된 작은 프로그램은 다음과 같은 출력을 생성하므로 정규 표현식으로 HTML을 구문 분석하면 원하는 작업에 적합하다는 것을 알 수 있습니다.

% html_input_rx Amazon.com-_Online_Shopping_for_Electronics,_Apparel,_Computers,_Books,_DVDs_\&_more.htm
input tag #1 at character 9955:
       class => "searchSelect"
          id => "twotabsearchtextbox"
        name => "field-keywords"
        size => "50"
       style => "width:100%; background-color: #FFF;"
       title => "Search for"
        type => "text"
       value => ""

input tag #2 at character 10335:
         alt => "Go"
         src => "http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V192234675_.gif"
        type => "image"

입력 태그 구문 분석, 악의없는 입력 참조

위의 출력을 생성 한 프로그램의 소스는 다음과 같습니다.

#!/usr/bin/env perl
#
# html_input_rx - pull out all <input> tags from (X)HTML src
#                  via simple regex processing
#
# Tom Christiansen <tchrist@perl.com>
# Sat Nov 20 10:17:31 MST 2010
#
################################################################

use 5.012;

use strict;
use autodie;
use warnings FATAL => "all";
use subs qw{
    see_no_evil
    parse_input_tags
    input descape dequote
    load_patterns
};
use open        ":std",
          IN => ":bytes",
         OUT => ":utf8";
use Encode qw< encode decode >;

    ###########################################################

                        parse_input_tags
                           see_no_evil
                              input

    ###########################################################

until eof(); sub parse_input_tags {
    my $_ = shift();
    our($Input_Tag_Rx, $Pull_Attr_Rx);
    my $count = 0;
    while (/$Input_Tag_Rx/pig) {
        my $input_tag = $+{TAG};
        my $place     = pos() - length ${^MATCH};
        printf "input tag #%d at character %d:\n", ++$count, $place;
        my %attr = ();
        while ($input_tag =~ /$Pull_Attr_Rx/g) {
            my ($name, $value) = @+{ qw< NAME VALUE > };
            $value = dequote($value);
            if (exists $attr{$name}) {
                printf "Discarding dup attr value '%s' on %s attr\n",
                    $attr{$name} // "<undef>", $name;
            }
            $attr{$name} = $value;
        }
        for my $name (sort keys %attr) {
            printf "  %10s => ", $name;
            my $value = descape $attr{$name};
            my  @Q; given ($value) {
                @Q = qw[  " "  ]  when !/'/ && !/"/;
                @Q = qw[  " "  ]  when  /'/ && !/"/;
                @Q = qw[  ' '  ]  when !/'/ &&  /"/;
                @Q = qw[ q( )  ]  when  /'/ &&  /"/;
                default { die "NOTREACHED" }
            }
            say $Q[0], $value, $Q[1];
        }
        print "\n";
    }

}

sub dequote {
    my $_ = $_[0];
    s{
        (?<quote>   ["']      )
        (?<BODY>
          (?s: (?! \k<quote> ) . ) *
        )
        \k<quote>
    }{$+{BODY}}six;
    return $_;
}

sub descape {
    my $string = $_[0];
    for my $_ ($string) {
        s{
            (?<! % )
            % ( \p{Hex_Digit} {2} )
        }{
            chr hex $1;
        }gsex;
        s{
            & \043
            ( [0-9]+ )
            (?: ;
              | (?= [^0-9] )
            )
        }{
            chr     $1;
        }gsex;
        s{
            & \043 x
            ( \p{ASCII_HexDigit} + )
            (?: ;
              | (?= \P{ASCII_HexDigit} )
            )
        }{
            chr hex $1;
        }gsex;

    }
    return $string;
}

sub input {
    our ($RX_SUBS, $Meta_Tag_Rx);
    my $_ = do { local $/; <> };
    my $encoding = "iso-8859-1";  # web default; wish we had the HTTP headers :(
    while (/$Meta_Tag_Rx/gi) {
        my $meta = $+{META};
        next unless $meta =~ m{             $RX_SUBS
            (?= http-equiv )
            (?&name)
            (?&equals)
            (?= (?&quote)? content-type )
            (?&value)
        }six;
        next unless $meta =~ m{             $RX_SUBS
            (?= content ) (?&name)
                          (?&equals)
            (?<CONTENT>   (?&value)    )
        }six;
        next unless $+{CONTENT} =~ m{       $RX_SUBS
            (?= charset ) (?&name)
                          (?&equals)
            (?<CHARSET>   (?&value)    )
        }six;
        if (lc $encoding ne lc $+{CHARSET}) {
            say "[RESETTING ENCODING $encoding => $+{CHARSET}]";
            $encoding = $+{CHARSET};
        }
    }
    return decode($encoding, $_);
}

sub see_no_evil {
    my $_ = shift();

    s{ <!    DOCTYPE  .*?         > }{}sx;
    s{ <! \[ CDATA \[ .*?    \]\] > }{}gsx;

    s{ <script> .*?  </script> }{}gsix;
    s{ <!--     .*?        --> }{}gsx;

    return $_;
}

sub load_patterns {

    our $RX_SUBS = qr{ (?(DEFINE)
        (?<nv_pair>         (?&name) (?&equals) (?&value)         )
        (?<name>            \b (?=  \pL ) [\w\-] + (?<= \pL ) \b  )
        (?<equals>          (?&might_white)  = (?&might_white)    )
        (?<value>           (?&quoted_value) | (?&unquoted_value) )
        (?<unwhite_chunk>   (?: (?! > ) \S ) +                    )
        (?<unquoted_value>  [\w\-] *                              )
        (?<might_white>     \s *                                  )
        (?<quoted_value>
            (?<quote>   ["']      )
            (?: (?! \k<quote> ) . ) *
            \k<quote>
        )
        (?<start_tag>  < (?&might_white) )
        (?<end_tag>
            (?&might_white)
            (?: (?&html_end_tag)
              | (?&xhtml_end_tag)
             )
        )
        (?<html_end_tag>       >  )
        (?<xhtml_end_tag>    / >  )
    ) }six;

    our $Meta_Tag_Rx = qr{                          $RX_SUBS
        (?<META>
            (?&start_tag) meta \b
            (?:
                (?&might_white) (?&nv_pair)
            ) +
            (?&end_tag)
        )
    }six;

    our $Pull_Attr_Rx = qr{                         $RX_SUBS
        (?<NAME>  (?&name)      )
                  (?&equals)
        (?<VALUE> (?&value)     )
    }six;

    our $Input_Tag_Rx = qr{                         $RX_SUBS

        (?<TAG> (?&input_tag) )

        (?(DEFINE)

            (?<input_tag>
                (?&start_tag)
                input
                (?&might_white)
                (?&attributes)
                (?&might_white)
                (?&end_tag)
            )

            (?<attributes>
                (?:
                    (?&might_white)
                    (?&one_attribute)
                ) *
            )

            (?<one_attribute>
                \b
                (?&legal_attribute)
                (?&might_white) = (?&might_white)
                (?:
                    (?&quoted_value)
                  | (?&unquoted_value)
                )
            )

            (?<legal_attribute>
                (?: (?&optional_attribute)
                  | (?&standard_attribute)
                  | (?&event_attribute)
            # for LEGAL parse only, comment out next line 
                  | (?&illegal_attribute)
                )
            )

            (?<illegal_attribute>  (?&name) )

            (?<required_attribute> (?#no required attributes) )

            (?<optional_attribute>
                (?&permitted_attribute)
              | (?&deprecated_attribute)
            )

            # NB: The white space in string literals 
            #     below DOES NOT COUNT!   It's just 
            #     there for legibility.

            (?<permitted_attribute>
                  accept
                | alt
                | bottom
                | check box
                | checked
                | disabled
                | file
                | hidden
                | image
                | max length
                | middle
                | name
                | password
                | radio
                | read only
                | reset
                | right
                | size
                | src
                | submit
                | text
                | top
                | type
                | value
            )

            (?<deprecated_attribute>
                  align
            )

            (?<standard_attribute>
                  access key
                | class
                | dir
                | ltr
                | id
                | lang
                | style
                | tab index
                | title
                | xml:lang
            )

            (?<event_attribute>
                  on blur
                | on change
                | on click
                | on dbl   click
                | on focus
                | on mouse down
                | on mouse move
                | on mouse out
                | on mouse over
                | on mouse up
                | on key   down
                | on key   press
                | on key   up
                | on select
            )
        )
    }six;

}

UNITCHECK {
    load_patterns();
}

END {
    close(STDOUT)
        || die "can't close stdout: $!";
} 

당신은 간다! 아무것도 아니야! 🙂

오직 당신 정규 표현식에와 당신의 기술이 특정 구문 분석 작업까지인지를 판단 할 수 있습니다. 모든 사람의 기술 수준은 다르며 모든 새로운 작업은 다릅니다. 잘 정의 된 입력 세트가있는 작업의 경우, 정규식이 올바른 선택입니다. 처리 할 HTML의 제한된 서브 세트가있을 때 일부를 조합하는 것이 쉽지 않기 때문입니다. 정규식 초보자조차도 정규식을 사용하여 이러한 작업을 처리해야합니다. 다른 것은 과잉입니다.

그러나 HTML이 잘 못 박 히기 시작하면 예측할 수 없지만 완벽하게 합법적 인 방식으로 시작하기 시작하면 더 많은 종류의 것들이나 더 복잡한 종속성을 일치시켜야하면 결국에는 구문 분석 클래스를 사용하는 것보다 정규 표현식을 사용하는 솔루션을 적용하려면 더 열심히 노력해야합니다. 그 손익 분기점이 떨어지는 곳은 다시 정규 표현식을 사용하는 편안함 수준에 달려 있습니다.

그래서 내가 무엇을해야하니?

당신이 해야 할 일이나 할 수없는 일 을 말하지 않겠습니다 . 나는 그것이 틀렸다고 생각한다. 나는 단지 당신에게 가능성을 제시하고 싶습니다, 당신의 눈을 조금여십시오. 당신은 당신이하고 싶은 일과 원하는 방법을 선택할 수 있습니다. 절대적인 것은 없으며, 자신과 마찬가지로 자신의 상황을 아는 사람은 없습니다. 무언가가 너무 많은 것처럼 보인다면 아마도 그럴 것입니다. 프로그래밍은 재미 있어야합니다 . 그렇지 않으면 잘못했을 수 있습니다.

하나 html_input_rx의 유효한 방법으로 내 프로그램을 볼 수 있습니다 . 그중 하나는 실제로 정규 표현식으로 HTML을 구문 분석 할 수 있다는 것 입니다. 그러나 다른 하나는 그것이 거의 모든 사람이 생각하는 것보다 훨씬, 훨씬, 훨씬 어렵다는 것입니다. 이것은 쉽게 내 프로그램은 당신이해야하는지에 대한 증거라는 결론으로 이어질 수 없는 정말 너무 어렵 기 때문에, 할.

나는 그것에 동의하지 않습니다. 확실히 내 프로그램에서 내가하는 모든 일이 약간의 연구 후에 이해가되지 않는다면, 이런 종류의 작업에 정규식을 사용하려고 시도해서는 안됩니다. 특정 HTML의 경우 정규 표현식은 훌륭하지만 일반적인 HTML의 경우 광기와 관련이 있습니다. 구문 분석 클래스를 항상 사용합니다. 특히 HTML 인 경우 직접 생성하지 않습니다.

에 대한 정규 표현식에 최적 작은 HTML 구문 분석 문제, 큰 사람을위한 pessimal

내 프로그램이 일반적인 HTML을 파싱하기 위해 정규 표현식을 사용 하지 않아야 하는 이유를 설명하는 경우에도 마찬가지입니다. 읽을 수없고, 구조화되지 않았으며, 유지할 수없는 패턴을 작성하는 불쾌하고 불쾌한 습관.

패턴은 추악 할 필요가 없으며 단단하지 않아도됩니다. 못생긴 패턴을 만들면 패턴이 아니라 자신을 반영합니다.

놀랍도록 절묘한 정규식 언어

귀하의 문제에 대한 나의 바람직한 해결책이 Perl로 작성되었음을 알려달라고 요청 받았습니다. 너 놀랐 니? 눈치 채지 못했습니까? 이 계시는 폭탄입니까?

다른 툴과 프로그래밍 언어가 Perl처럼 정규 표현식에있어 편리하고 표현력이 뛰어나고 강력하지는 않습니다. 큰 스펙트럼이 있으며 일부는 다른 것보다 더 적합합니다. 일반적으로 라이브러리 대신 핵심 언어의 일부로 정규 표현식을 표현한 언어는 작업하기가 더 쉽습니다. C를 사용하는 경우 프로그램을 다르게 구성하더라도 PCRE와 같이 할 수없는 정규 표현식으로 아무것도하지 않았습니다.

결국 Perl이 이제 정규식이라는 관점에서 다른 언어를 따라 잡을 수 있습니다. 나는 이것이 Perl이 시작되었을 때 펄의 정규식과 같은 것을 가진 사람이 없기 때문에 이것을 말한다. 당신이 좋아하는 것을 말하지만, 이것은 Perl이 분명히 얻은 곳입니다. 모든 사람들은 Perl의 정규식을 개발 단계마다 다르지만 복사했습니다. Perl은 사용하는 도구 나 언어에 상관없이 오늘날 현대 패턴에 의존하는 거의 모든 것 (거의 전부는 아니지만 거의)을 개척했습니다. 결국 다른 사람들 따라 잡을 것입니다.

그러나 그들은 지금처럼 과거에 Perl이 있었던 곳까지만 따라 잡을 것입니다. 모든 것이 발전합니다. Perl이 이끄는 다른 것이 없다면 정규 표현식에서 다른 사람들이 따릅니다. 펄은 이제 다른 사람들이 펄이있는 곳을 따라 잡을 수 있을까요? 나도 몰라, 그러나 우리도 움직일 것입니다. 아마도 우리는 Perl₆의 제작 패턴 스타일에 더 가까울 것 입니다.

그런 종류의 것을 좋아하지만 Perl₅에서 사용하고 싶다면 Damian Conway의 멋진 Regexp :: Grammars 모듈에 관심이있을 것 입니다. 완전히 훌륭하고 내 프로그램에서 내가 한 일이 사람들이 공백이나 알파벳 식별자없이 함께 모은 패턴을 만드는 것처럼 원시적 인 것처럼 보입니다. 확인 해봐!


간단한 HTML Chunker

다음은이 게시물의 시작 부분에서 중심을 보여준 파서의 완전한 소스입니다.

나는 엄격히 테스트 된 파싱 클래스보다 이것을 사용해야한다고 제안 하지 않습니다 . 하지만 난 그냥 때문에 정규 표현식에와 그 누구도 할 수있는 구문 분석 HTML 척없는 사람들의 피곤 그들이 할 수 없습니다입니다. 당신은 분명히 할 수 있으며,이 프로그램은 그 주장의 증거입니다.

물론, 그것은 쉬운 일이 아닙니다, 그러나 그것은 이다 가능!

좋은 구문 분석 클래스는 어떤 존재하기 때문에 그렇게하려고 노력하는 것은 시간의 끔찍한 낭비입니다 해야 이 작업을 위해 사용합니다. 임의의 HTML 을 구문 분석하려는 사람들에게 정답 은 불가능하다는 것이 아닙니다 . 그것은 쉽고 해가없는 대답입니다. 정직하고 정직한 대답은 처음부터 파악하기에는 너무 귀찮기 때문에 시도하지 않아야한다는 것입니다. 그들은 완벽하게 잘 작동하는 바퀴를 되살리려 고 애 쓰지 말아야합니다.

반면, 예측 가능한 하위 집합에 속하는 HTML 은 정규 표현식으로 구문 분석하기가 매우 쉽습니다. 작은 문제, 장난감 문제, 아마도 쉬운 일이 없기 때문에 사람들이 사용하려고하는 것은 놀라운 일이 아닙니다. 그렇기 때문에 두 가지 작업 (특정 대 일반)을 구별하는 것이 매우 중요한 이유는 동일한 접근 방식을 요구하지 않기 때문입니다.

앞으로 HTML 및 정규 표현식에 대한 질문에 대한 공정하고 정직한 처리가 이루어지기를 바랍니다.

여기 내 HTML 어휘 분석기가있다. 유효성 검사 구문 분석을 시도하지 않습니다. 어휘 요소 만 식별합니다. HTML 파서보다 HTML 청커 로 생각할 수도 있습니다 . 깨진 HTML을 용서하지는 않지만 그 방향으로 약간의 여유를줍니다.

전체 HTML을 직접 구문 분석하지 않아도 (그리고 왜해야합니까? 해결 된 문제입니다!),이 프로그램에는 많은 사람들이 많이 배울 수 있다고 생각하는 멋진 정규식 비트가 많이 있습니다. 즐겨!

#!/usr/bin/env perl
#
# chunk_HTML - a regex-based HTML chunker
#
# Tom Christiansen <tchrist@perl.com
#   Sun Nov 21 19:16:02 MST 2010
########################################

use 5.012;

use strict;
use autodie;
use warnings qw< FATAL all >;
use open     qw< IN :bytes OUT :utf8 :std >;

MAIN: {
  $| = 1;
  lex_html(my $page = slurpy());
  exit();
}

########################################################################
sub lex_html {
    our $RX_SUBS;                                        ###############
    my  $html = shift();                                 # Am I...     #
    for (;;) {                                           # forgiven? :)#
        given ($html) {                                  ###############
            last                when (pos || 0) >= length;
            printf "\@%d=",          (pos || 0);
            print  "doctype "   when / \G (?&doctype)  $RX_SUBS  /xgc;
            print  "cdata "     when / \G (?&cdata)    $RX_SUBS  /xgc;
            print  "xml "       when / \G (?&xml)      $RX_SUBS  /xgc;
            print  "xhook "     when / \G (?&xhook)    $RX_SUBS  /xgc;
            print  "script "    when / \G (?&script)   $RX_SUBS  /xgc;
            print  "style "     when / \G (?&style)    $RX_SUBS  /xgc;
            print  "comment "   when / \G (?&comment)  $RX_SUBS  /xgc;
            print  "tag "       when / \G (?&tag)      $RX_SUBS  /xgc;
            print  "untag "     when / \G (?&untag)    $RX_SUBS  /xgc;
            print  "nasty "     when / \G (?&nasty)    $RX_SUBS  /xgc;
            print  "text "      when / \G (?&nontag)   $RX_SUBS  /xgc;
            default {
                die "UNCLASSIFIED: " .
                  substr($_, pos || 0, (length > 65) ? 65 : length);
            }
        }
    }
    say ".";
}
#####################
# Return correctly decoded contents of next complete
# file slurped in from the <ARGV> stream.
#
sub slurpy {
    our ($RX_SUBS, $Meta_Tag_Rx);
    my $_ = do { local $/; <ARGV> };   # read all input

    return unless length;

    use Encode   qw< decode >;

    my $bom = "";
    given ($_) {
        $bom = "UTF-32LE" when / ^ \xFf \xFe \0   \0   /x;  # LE
        $bom = "UTF-32BE" when / ^ \0   \0   \xFe \xFf /x;  #   BE
        $bom = "UTF-16LE" when / ^ \xFf \xFe           /x;  # le
        $bom = "UTF-16BE" when / ^ \xFe \xFf           /x;  #   be
        $bom = "UTF-8"    when / ^ \xEF \xBB \xBF      /x;  # st00pid
    }
    if ($bom) {
        say "[BOM $bom]";
        s/^...// if $bom eq "UTF-8";                        # st00pid

        # Must use UTF-(16|32) w/o -[BL]E to strip BOM.
        $bom =~ s/-[LB]E//;

        return decode($bom, $_);

        # if BOM found, don't fall through to look
        #  for embedded encoding spec
    }

    # Latin1 is web default if not otherwise specified.
    # No way to do this correctly if it was overridden
    # in the HTTP header, since we assume stream contains
    # HTML only, not also the HTTP header.
    my $encoding = "iso-8859-1";
    while (/ (?&xml) $RX_SUBS /pgx) {
        my $xml = ${^MATCH};
        next unless $xml =~ m{              $RX_SUBS
            (?= encoding )  (?&name)
                            (?&equals)
                            (?&quote) ?
            (?<ENCODING>    (?&value)       )
        }sx;
        if (lc $encoding ne lc $+{ENCODING}) {
            say "[XML ENCODING $encoding => $+{ENCODING}]";
            $encoding = $+{ENCODING};
        }
    }

    while (/$Meta_Tag_Rx/gi) {
        my $meta = $+{META};

        next unless $meta =~ m{             $RX_SUBS
            (?= http-equiv )    (?&name)
                                (?&equals)
            (?= (?&quote)? content-type )
                                (?&value)
        }six;

        next unless $meta =~ m{             $RX_SUBS
            (?= content )       (?&name)
                                (?&equals)
            (?<CONTENT>         (?&value)    )
        }six;

        next unless $+{CONTENT} =~ m{       $RX_SUBS
            (?= charset )       (?&name)
                                (?&equals)
            (?<CHARSET>         (?&value)    )
        }six;

        if (lc $encoding ne lc $+{CHARSET}) {
            say "[HTTP-EQUIV ENCODING $encoding => $+{CHARSET}]";
            $encoding = $+{CHARSET};
        }
    }

    return decode($encoding, $_);
}
########################################################################
# Make sure to this function is called
# as soon as source unit has been compiled.
UNITCHECK { load_rxsubs() }

# useful regex subroutines for HTML parsing
sub load_rxsubs {

    our $RX_SUBS = qr{
      (?(DEFINE)

        (?<WS> \s *  )

        (?<any_nv_pair>     (?&name) (?&equals) (?&value)         )
        (?<name>            \b (?=  \pL ) [\w:\-] +  \b           )
        (?<equals>          (?&WS)  = (?&WS)    )
        (?<value>           (?&quoted_value) | (?&unquoted_value) )
        (?<unwhite_chunk>   (?: (?! > ) \S ) +                    )

        (?<unquoted_value>  [\w:\-] *                             )

        (?<any_quote>  ["']      )

        (?<quoted_value>
            (?<quote>   (?&any_quote)  )
            (?: (?! \k<quote> ) . ) *
            \k<quote>
        )

        (?<start_tag>       < (?&WS)      )
        (?<html_end_tag>      >           )
        (?<xhtml_end_tag>   / >           )
        (?<end_tag>
            (?&WS)
            (?: (?&html_end_tag)
              | (?&xhtml_end_tag) )
         )

        (?<tag>
            (?&start_tag)
            (?&name)
            (?:
                (?&WS)
                (?&any_nv_pair)
            ) *
            (?&end_tag)
        )

        (?<untag> </ (?&name) > )

        # starts like a tag, but has screwed up quotes inside it
        (?<nasty>
            (?&start_tag)
            (?&name)
            .*?
            (?&end_tag)
        )

        (?<nontag>    [^<] +            )

        (?<string> (?&quoted_value)     )
        (?<word>   (?&name)             )

        (?<doctype>
            <!DOCTYPE
                # please don't feed me nonHTML
                ### (?&WS) HTML
            [^>]* >
        )

        (?<cdata>   <!\[CDATA\[     .*?     \]\]    > )
        (?<script>  (?= <script ) (?&tag)   .*?     </script> )
        (?<style>   (?= <style  ) (?&tag)   .*?     </style> )
        (?<comment> <!--            .*?           --> )

        (?<xml>
            < \? xml
            (?:
                (?&WS)
                (?&any_nv_pair)
            ) *
            (?&WS)
            \? >
        )

        (?<xhook> < \? .*? \? > )

      )

    }six;

    our $Meta_Tag_Rx = qr{                          $RX_SUBS
        (?<META>
            (?&start_tag) meta \b
            (?:
                (?&WS) (?&any_nv_pair)
            ) +
            (?&end_tag)
        )
    }six;

}

# nobody *ever* remembers to do this!
END { close STDOUT }

답변

  1. tchrist처럼 소설을 쓸 수 있습니다
  2. DOM 라이브러리, HTML을로드하고 xpath를 사용하고을 사용할 수 있습니다 //input[@type="hidden"]. 또는 xpath를 사용하지 않으려면 모든 입력을 가져 와서 숨겨지는 입력을 필터링하십시오 getAttribute.

나는 # 2를 선호합니다.

<?php

$d = new DOMDocument();
$d->loadHTML(
    '
    <p>fsdjl</p>
    <form><div>fdsjl</div></form>
    <input type="hidden" name="blah" value="hide yo kids">
    <input type="text" name="blah" value="hide yo kids">
    <input type="hidden" name="blah" value="hide yo wife">
');
$x = new DOMXpath($d);
$inputs = $x->evaluate('//input[@type="hidden"]');

foreach ( $inputs as $input ) {
    echo $input->getAttribute('value'), '<br>';
}

결과:

hide yo kids<br>hide yo wife<br>

답변

Tom Christiansen의 렉서 솔루션의 정신으로, 여기에 잊혀진 Robert Cameron의 기사 REX : 정규 표현식을 사용한 XML 얕은 구문 분석에 대한 링크가 있습니다.

http://www.cs.sfu.ca/~cameron/REX.html

요약

XML 구문은 XML 문서를 단일 정규식을 사용하여 마크 업 및 텍스트 항목 목록으로 구문 분석 할 수있을 정도로 간단합니다. XML 문서의 이러한 간단한 구문 분석은 다양한 경량 XML 처리 도구를 구성하는 데 매우 유용 할 수 있습니다. 그러나 복잡한 정규식은 구성하기가 어렵고 읽기가 더 어려울 수 있습니다. 이 논문은 정규 표현식을위한 문해력있는 프로그래밍 형태를 사용하여 단순하고 정확하며 효율적이며 강력하며 언어에 독립적 인 XML 얕은 구문 분석의 기초로 사용될 수있는 XML 얕은 구문 분석 표현식을 문서화합니다. Perl, JavaScript 및 Lex / Flex에서 각각 50 줄 미만의 완전한 얕은 파서 구현도 제공됩니다.

정규식에 대해 읽는 것을 좋아한다면 Cameron의 논문은 흥미 롭습니다. 그의 글은 간결하고 철저하며 매우 상세합니다. 그는 단순히 REX 정규 표현식을 구성하는 방법뿐만 아니라 작은 부분에서 복잡한 정규 표현식을 작성하는 방법을 보여줍니다.

REX 정규식을 10 년 동안 사용하거나 사용하지 않아 초기 포스터에 대해 제기 한 문제를 해결했습니다 (이 특정 태그와 어떻게 일치하지만 다른 유사한 태그는 어떻게 일치하지 않습니까?). 나는 그가 개발 한 정규식이 완전히 신뢰할 만하다는 것을 알았습니다.

REX는 문서의 어휘 적 세부 사항에 초점을 맞출 때 특히 유용합니다. 예를 들어 한 종류의 텍스트 문서 (예 : 일반 텍스트, XML, SGML, HTML)를 다른 유형의 문서로 변환 할 때 유용합니다. 대부분의 변형에 대해 잘 형성되거나 파싱 가능합니다. 문서의 나머지 부분을 방해하지 않으면 서 문서의 어느 곳에서나 마크 업을 대상으로 할 수 있습니다.


답변

나는이 답변의 나머지 내용을 좋아하지만 실제로 질문에 직접 또는 올바르게 대답하지는 않았습니다. 플래티넘의 대답조차도 지나치게 복잡했고 효율성도 떨어졌습니다. 그래서 나는 이것을 넣어야했습니다.

나는 올바르게 사용될 때 Regex의 큰 지지자입니다. 그러나 낙인 (및 성능) 때문에 항상 올바른 형식의 XML 또는 HTML이 XML 파서를 사용해야한다고 말합니다. 더 나은 성능은 문자열 파싱이지만, 너무 손이 잘 들지 않으면 가독성 사이에 경계가 있습니다. 그러나 그것은 문제가 아닙니다. 문제는 숨겨진 유형의 입력 태그를 일치시키는 방법입니다. 정답은:

<input[^>]*type="hidden"[^>]*>

특징에 따라 포함해야 할 유일한 정규식 옵션은 ignorecase 옵션입니다.


답변

당신은 이것을 시도 할 수 있습니다 :

<[A-Za-z ="/_0-9+]*>

더 가까운 결과를 얻으려면 다음을 시도하십시오.

<[ ]*input[ ]+type="hidden"[ ]*name=[A-Za-z ="_0-9+]*[ ]*[/]*>

http://regexpal.com/에서 정규식 패턴을 테스트 할 수 있습니다.

이 패튼은 이것에 좋습니다 :

<input type="hidden" name="SaveRequired" value="False" /><input type="hidden" name="__VIEWSTATE1" value="1H4sIAAtzrkX7QfL5VEGj6nGi+nP" /><input type="hidden" name="__VIEWSTATE2" value="0351118MK" /><input type="hidden" name="__VIEWSTATE3" value="ZVVV91yjY" />

과의 임의의 순서를 위해 type, name그리고 valueu는 이것을 사용할 수 있습니다 :

<[ ]*input[ ]*[A-Za-z ="_0-9+/]*>

또는

<[ ]*input[ ]*[A-Za-z ="_0-9+/]*[ ]*[/]>

이에 :

<input  name="SaveRequired" type="hidden" value="False" /><input type="hidden" name="__VIEWSTATE1" value="1H4sIAAtzrkX7QfL5VEGj6nGi+nP" /><input type="hidden" name="__VIEWSTATE2" value="0351118MK" /><input  name="__VIEWSTATE3" type="hidden" value="ZVVV91yjY" />

`

그건 그렇고 나는 당신이 이와 같은 것을 원한다고 생각합니다 :

<[ ]*input(([ ]*type="hidden"[ ]*name=[A-Za-z0-9_+"]*[ ]*value=[A-Za-z0-9_+"]*[ ]*)+)[ ]*/>|<[ ]*input(([ ]*type="hidden"[ ]*value=[A-Za-z0-9_+"]*[ ]*name=[A-Za-z0-9_+"]*[ ]*)+)[ ]*/>|<[ ]*input(([ ]*name=[A-Za-z0-9_+"]*[ ]*type="hidden"[ ]*value=[A-Za-z0-9_+"]*[ ]*)+)[ ]*/>|<[ ]*input(([ ]*value=[A-Za-z0-9_+"]*[ ]*type="hidden"[ ]*name=[A-Za-z0-9_+"]*[ ]*)+)[ ]*/>|<[ ]*input(([ ]*name=[A-Za-z0-9_+"]*[ ]*value=[A-Za-z0-9_+"]*[ ]*type="hidden"[ ]*)+)[ ]*/>|<[ ]*input(([ ]*value=[A-Za-z0-9_+"]*[ ]*name=[A-Za-z0-9_+"]*[ ]*type="hidden"[ ]*)+)[ ]*/>

좋지는 않지만 어떤 식 으로든 작동합니다.

http://regexpal.com/ 에서 테스트하십시오.


답변

**DOMDocument**html 코드를 추출하는 데 사용 하고 싶습니다 .

$dom = new DOMDocument();
$dom ->loadHTML($input);
$x = new DOMXpath($dom );
$results = $x->evaluate('//input[@type="hidden"]');

foreach ( $results as $item) {
    print_r( $item->getAttribute('value') );
}

BTW, 당신은 여기에서 테스트 할 수 있습니다-regex101.com. 실시간으로 결과를 보여줍니다. Regexp에 대한 몇 가지 규칙 : http://www.eclipse.org/tptp/home/downloads/installguide/gla_42/ref/rregexp.html
Reader .