Phải làm gì Mẫu biểu thức chính quy không khớp với bất kỳ vị trí nào trong chuỗi?


181

Tôi đang cố gắng khớp các trường <input>loại ẩn ẩn của dòng sử dụng mẫu này:

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

Đây là dữ liệu mẫu mẫu:

<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="" />

Nhưng tôi không chắc chắn rằng type, namevaluethuộc tính sẽ luôn xuất hiện theo thứ tự. Nếu typethuộc tính xuất hiện lần cuối, trận đấu sẽ thất bại vì trong mẫu của tôi, nó bắt đầu.

Câu hỏi:
Làm thế nào tôi có thể thay đổi mẫu của mình để nó phù hợp bất kể vị trí của các thuộc tính trong <input>thẻ?

PS: Nhân tiện , tôi đang sử dụng Công cụ RegEx Desktop dựa trên Adobe Air để kiểm tra các biểu thức thông thường.


4
regex là giải pháp tuyệt vời nếu bạn có quyền kiểm soát html được tạo bởi vì nó là cuộc tranh luận không phải là tranh luận thường xuyên, nhưng trường hợp của tôi tôi không biết html sẽ thay đổi như thế nào trong tương lai nên điều tốt nhất là sử dụng trình phân tích cú pháp thay vì regex, tôi đã sử dụng regex trong dự án của tôi ở những phần mà tôi có quyền kiểm soát
Salman

Câu trả lời:


108

Trái với tất cả các câu trả lời ở đây, vì những gì bạn đang cố gắng thực hiện regex là một giải pháp hoàn toàn hợp lệ. Điều này là do bạn KHÔNG cố gắng khớp các thẻ cân bằng-- Điều đó là không thể với regex! Nhưng bạn chỉ khớp những gì trong một thẻ và điều đó hoàn toàn đều đặn.

Đây là vấn đề, mặc dù. Bạn không thể làm điều đó chỉ với một regex ... bạn cần thực hiện một trận đấu để thu được một <input>thẻ, sau đó xử lý thêm về điều đó. Lưu ý rằng điều này sẽ chỉ hoạt động nếu không có giá trị thuộc tính nào có >ký tự trong đó, vì vậy nó không hoàn hảo, nhưng nó đủ cho các đầu vào lành mạnh.

Đây là một số mã Perl (giả) để cho bạn biết ý tôi là gì:

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
}

Nguyên tắc cơ bản ở đây là, đừng cố gắng làm quá nhiều với một biểu thức chính quy. Như bạn nhận thấy, các biểu thức chính quy thực thi một số lượng đơn đặt hàng nhất định. Vì vậy, những gì bạn cần làm thay vào đó là trước tiên khớp với TIẾP THEO những gì bạn đang cố gắng trích xuất, sau đó thực hiện gửi dữ liệu bạn muốn.

EDIT: Tuy nhiên, tôi sẽ đồng ý rằng nói chung, sử dụng trình phân tích cú pháp HTML có thể dễ dàng và tốt hơn và bạn thực sự nên xem xét việc thiết kế lại mã của mình hoặc kiểm tra lại các mục tiêu của mình. :-) Nhưng tôi đã phải đăng câu trả lời này như một phản ứng với phản ứng giật đầu gối rằng việc phân tích bất kỳ tập hợp con nào của HTML là không thể: HTML và XML đều bất thường khi bạn xem xét toàn bộ đặc tả, nhưng đặc điểm kỹ thuật của thẻ là thường xuyên , chắc chắn trong sức mạnh của PCRE.


14
Không trái với tất cả các câu trả lời ở đây. :)
tchrist

6
@tchrist: Câu trả lời của bạn không có ở đây khi tôi đăng bài của tôi. ;-)
Bạch kim Azure

7
yah tốt - vì một số lý do khiến tôi mất nhiều thời gian hơn so với bạn đã làm. Tôi nghĩ rằng bàn phím của tôi cần phải bôi trơn. :)
tchrist

6
Đó là HTML không hợp lệ - nó phải là value = "& lt; Bạn có thực sự chắc chắn về điều này không? & Gt;" Nếu nơi mà anh ta cào bằng làm một công việc tồi tệ thoát khỏi những thứ như thế này, thì anh ta sẽ cần một giải pháp tinh vi hơn - nhưng nếu họ làm đúng (và nếu anh ta kiểm soát được nó, anh ta nên chắc chắn rằng nó đúng).
Ross Snyder

14
Liên kết bắt buộc với câu trả lời SO tốt nhất về chủ đề (có thể là thời gian trả lời SO tốt nhất): stackoverflow.com/questions/1732348/ Kẻ
Daniel Ribeiro

682

Ồ Có, bạn có thể sử dụng Regexes để phân tích HTML!

Đối với nhiệm vụ bạn đang cố gắng, regexes hoàn toàn tốt!

Đúng hầu hết mọi người đều đánh giá thấp sự khó khăn của việc phân tích cú pháp HTML bằng các biểu thức thông thường và do đó làm rất kém.

Nhưng đây không phải là một lỗ hổng cơ bản liên quan đến lý thuyết tính toán. Sự điên cuồng đó được vẹt rất nhiều ở đây , nhưng bạn không tin họ.

Vì vậy, trong khi nó chắc chắn có thể được thực hiện (bài đăng này đóng vai trò là bằng chứng tồn tại của thực tế không thể chuyển đổi này), điều đó không có nghĩa là nó  phải  như vậy.

Bạn phải tự quyết định xem bạn có nhiệm vụ viết số tiền cho một trình phân tích cú pháp HTML chuyên dụng, chuyên dụng ra khỏi các biểu thức chính quy hay không. Hầu hết mọi người không.

Nhưng tôi là. ☻


Các giải pháp phân tích cú pháp HTML dựa trên Regex chung

Đầu tiên tôi sẽ chỉ ra cách dễ dàng phân tích HTML tùy ý với các biểu thức chính quy. Chương trình đầy đủ ở cuối bài đăng này, nhưng trung tâm của trình phân tích cú pháp là:

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);
    }
  }
}

Xem nó dễ đọc như thế nào?

Như được viết, nó xác định từng đoạn HTML và cho biết nơi nó tìm thấy mảnh đó. Bạn có thể dễ dàng sửa đổi nó để làm bất cứ điều gì khác mà bạn muốn với bất kỳ loại mảnh cụ thể nào, hoặc cho các loại cụ thể hơn loại này.

Tôi không gặp trường hợp thử nghiệm nào (bên trái :): Tôi đã chạy thành công mã này trên hơn 100.000 tệp HTML - mỗi một tệp tôi có thể nhanh chóng và dễ dàng sử dụng. Ngoài những thứ đó, tôi cũng chạy nó trên các tệp được xây dựng đặc biệt để phá vỡ các trình phân tích cú pháp ngây thơ.

Đây không phải là một trình phân tích cú pháp ngây thơ.

Ồ, tôi chắc chắn nó không hoàn hảo, nhưng tôi vẫn chưa thể phá vỡ nó. Tôi nghĩ rằng ngay cả khi một cái gì đó đã làm, sửa chữa sẽ dễ dàng phù hợp vì cấu trúc rõ ràng của chương trình. Ngay cả các chương trình regex-heavy nên có cấu trúc.

Bây giờ đã hết cách, hãy để tôi giải quyết câu hỏi của OP.

Bản trình diễn giải quyết nhiệm vụ của OP bằng cách sử dụng Regexes

html_input_rxChương trình nhỏ mà tôi đưa vào dưới đây tạo ra kết quả đầu ra sau đây, để bạn có thể thấy rằng phân tích cú pháp HTML bằng regexes hoạt động tốt cho những gì bạn muốn làm:

% 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"

Thẻ đầu vào phân tích cú pháp, không thấy đầu vào xấu

Đây là nguồn cho chương trình tạo ra đầu ra ở trên.

#!/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: $!";
} 

Có bạn đi! Không có gì với nó! :)

Chỉ bạn mới có thể đánh giá xem kỹ năng của bạn với regexes có phụ thuộc vào bất kỳ tác vụ phân tích cụ thể nào không. Trình độ kỹ năng của mọi người là khác nhau, và mọi nhiệm vụ mới đều khác nhau. Đối với các công việc mà bạn có một bộ đầu vào được xác định rõ ràng, regexes rõ ràng là lựa chọn đúng đắn, bởi vì việc kết hợp một số thứ nhỏ lại với nhau khi bạn có một tập hợp con hạn chế của HTML để xử lý. Ngay cả những người mới bắt đầu regex cũng nên xử lý những công việc đó bằng regexes. Bất cứ điều gì khác là quá mức cần thiết.

Tuy nhiên , một khi HTML bắt đầu trở nên ít bị đóng đinh hơn, một khi nó bắt đầu lan man theo những cách bạn không thể dự đoán nhưng hoàn toàn hợp pháp, một khi bạn phải đối chiếu nhiều loại khác nhau hơn hoặc với các phụ thuộc phức tạp hơn, cuối cùng bạn sẽ đạt đến điểm bạn phải làm việc chăm chỉ hơn để tạo ra một giải pháp sử dụng các biểu thức chính quy hơn là bạn phải sử dụng một lớp phân tích cú pháp. Trường hợp điểm hòa vốn rơi lại phụ thuộc vào mức độ thoải mái của bạn với biểu thức chính quy.

Vậy tôi nên làm gì?

Tôi sẽ không nói với bạn những gì bạn phải làm hoặc những gì bạn không thể làm. Tôi nghĩ đó là sai. Tôi chỉ muốn tặng bạn những khả năng, mở mắt ra một chút. Bạn có thể chọn những gì bạn muốn làm và cách bạn muốn làm điều đó. Không có sự tuyệt đối - và không ai khác biết được tình huống của bạn cũng như chính bạn làm. Nếu một cái gì đó có vẻ như quá nhiều công việc, tốt, có lẽ nó là. Lập trình nên vui , bạn biết đấy. Nếu không, bạn có thể làm sai.

Người ta có thể nhìn vào html_input_rxchương trình của tôi theo bất kỳ số cách hợp lệ nào. Một trong số đó là bạn thực sự có thể phân tích HTML bằng các biểu thức thông thường. Nhưng một điều nữa là nó rất nhiều, rất nhiều, khó hơn nhiều so với hầu hết mọi người từng nghĩ. Điều này có thể dễ dàng dẫn đến kết luận rằng chương trình của tôi là một minh chứng cho những gì bạn không nên làm, bởi vì nó thực sự quá khó.

Tôi sẽ không đồng ý với điều đó. Chắc chắn nếu mọi thứ tôi làm trong chương trình của tôi không có ý nghĩa với bạn sau một số nghiên cứu, thì bạn không nên cố gắng sử dụng regexes cho loại nhiệm vụ này. Đối với HTML cụ thể, biểu thức chính là tuyệt vời, nhưng đối với HTML chung, chúng tương đương với sự điên rồ. Tôi sử dụng các lớp phân tích cú pháp mọi lúc, đặc biệt nếu đó là HTML tôi không tự tạo.

Regexes tối ưu cho các vấn đề phân tích cú pháp HTML nhỏ , bi quan cho những vấn đề lớn

Ngay cả khi chương trình của tôi được lấy làm minh họa cho lý do tại sao bạn không nên sử dụng regexes để phân tích cú pháp HTML chung - điều đó cũng không sao, bởi vì tôi có nghĩa là nó - nó vẫn phải là một công cụ mở rộng để mọi người phá vỡ sự phổ biến khủng khiếp và thói quen khó chịu, khó chịu của việc viết các mẫu không thể đọc được, không có cấu trúc và không thể nhầm lẫn.

Các mẫu không phải là xấu, và chúng không phải là khó. Nếu bạn tạo ra các mẫu xấu xí, đó là một sự phản ánh về bạn, không phải chúng.

Ngôn ngữ Regex tinh tế phi thường

Tôi đã được yêu cầu chỉ ra rằng giải pháp chuyên sâu của tôi cho vấn đề của bạn đã được viết bằng Perl. Bạn có ngạc nhiên không Bạn đã không chú ý? Đây có phải là sự mặc khải?

Đúng là không phải tất cả các công cụ và ngôn ngữ lập trình khác đều khá tiện lợi, biểu cảm và mạnh mẽ khi nói đến regex như Perl. Có một phổ lớn ngoài kia, với một số phù hợp hơn những cái khác. Nói chung, các ngôn ngữ đã thể hiện regex như một phần của ngôn ngữ cốt lõi thay vì như một thư viện sẽ dễ làm việc hơn. Tôi đã không làm gì với các biểu thức mà bạn không thể thực hiện, giả sử, PCRE, mặc dù bạn sẽ cấu trúc chương trình khác đi nếu bạn đang sử dụng C.

Cuối cùng, các ngôn ngữ khác sẽ bắt kịp với nơi Perl hiện đang xét về các biểu thức chính quy. Tôi nói điều này bởi vì khi Perl bắt đầu, không ai khác có bất cứ thứ gì như biểu thức của Perl. Nói bất cứ điều gì bạn thích, nhưng đây là nơi Perl giành chiến thắng rõ ràng: mọi người đều sao chép các biểu thức của Perl mặc dù ở các giai đoạn phát triển khác nhau. Perl đã tiên phong gần như (không hoàn toàn là tất cả, nhưng gần như) tất cả mọi thứ mà bạn đã dựa vào trong các mẫu hiện đại ngày nay, bất kể bạn sử dụng công cụ hay ngôn ngữ nào. Vì vậy, cuối cùng những người khác sẽ bắt kịp.

Nhưng họ sẽ chỉ bắt kịp nơi Perl đã từng ở trong quá khứ, giống như bây giờ. Mọi thứ tiến bộ. Trong regexes nếu không có gì khác, nơi Perl dẫn, những người khác làm theo. Perl sẽ ở đâu khi mọi người cuối cùng cũng bắt kịp nơi Perl đang ở bây giờ? Tôi không có ý tưởng, nhưng tôi biết chúng ta cũng sẽ di chuyển. Có lẽ chúng ta sẽ gần gũi hơn với phong cách chế tạo của Perl₆ .

Nếu bạn thích loại điều đó nhưng muốn sử dụng nó trong Perl₅, bạn có thể quan tâm đến mô-đun Regapi :: Grammars tuyệt vời của Damian Conway . Nó hoàn toàn tuyệt vời, và làm cho những gì tôi đã làm ở đây trong chương trình của tôi có vẻ nguyên thủy như của tôi làm cho các mẫu mà mọi người nhồi nhét vào nhau mà không có khoảng trắng hoặc định danh chữ cái. Kiểm tra nó ra!


Chunker HTML đơn giản

Đây là nguồn hoàn chỉnh cho trình phân tích cú pháp mà tôi đã chỉ ra tâm điểm từ đầu bài đăng này.

Tôi không gợi ý rằng bạn nên sử dụng điều này trên một lớp phân tích cú pháp được kiểm tra nghiêm ngặt. Nhưng tôi mệt mỏi với những người giả vờ rằng không ai có thể phân tích HTML bằng các biểu thức chính chỉ vì họ không thể. Bạn rõ ràng có thể, và chương trình này là bằng chứng cho sự khẳng định đó.

Chắc chắn, nó không phải là dễ dàng, nhưng có thể!

Và cố gắng làm như vậy là một sự lãng phí thời gian khủng khiếp, bởi vì các lớp phân tích cú pháp tốt tồn tại mà bạn nên sử dụng cho nhiệm vụ này. Câu trả lời đúng cho những người cố gắng phân tích HTML tùy ý không phải là không thể. Đó là một câu trả lời dễ hiểu và không lịch sự. Câu trả lời chính xác và trung thực là họ không nên thử nó vì quá bận tâm để tìm ra từ đầu; họ không nên bẻ lưng phấn đấu để tái tạo một bánh xe hoạt động hoàn hảo.

Mặt khác, HTML nằm trong một tập hợp con có thể dự đoán là cực kỳ dễ phân tích cú pháp. Không có gì lạ khi mọi người cố gắng sử dụng chúng, bởi vì đối với các vấn đề nhỏ, có lẽ vấn đề về đồ chơi, không có gì có thể dễ dàng hơn. Đó là lý do tại sao việc phân biệt hai nhiệm vụ - cụ thể và chung chung - vì những điều này không nhất thiết đòi hỏi cùng một cách tiếp cận.

Tôi hy vọng trong tương lai ở đây sẽ thấy một cách đối xử công bằng và trung thực hơn đối với các câu hỏi về HTML và biểu thức chính quy.

Đây là từ điển HTML của tôi. Nó không cố gắng thực hiện một phân tích xác thực; nó chỉ xác định các yếu tố từ vựng. Bạn có thể nghĩ về nó nhiều hơn như một đoạn mã HTML hơn là trình phân tích cú pháp HTML. Nó không tha thứ cho HTML bị hỏng, mặc dù nó tạo ra một số khoản trợ cấp rất nhỏ theo hướng đó.

Ngay cả khi bạn không bao giờ tự phân tích HTML đầy đủ (và tại sao bạn nên giải quyết vấn đề!), Chương trình này có rất nhiều bit regex thú vị mà tôi tin rằng nhiều người có thể học hỏi được rất nhiều. Thưởng thức!

#!/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 }

23
hai điểm nổi bật từ nhận xét của bạn "Tôi sử dụng các lớp phân tích cú pháp mọi lúc, đặc biệt nếu đó là HTML tôi không tự tạo." và "Các mẫu không phải là xấu, và chúng không phải là khó. Nếu bạn tạo các mẫu xấu, đó là một sự phản ánh về bạn, không phải chúng." Tôi hoàn toàn đồng ý với những gì bạn đã nói, vì vậy tôi đang đánh giá lại vấn đề. cảm ơn rất nhiều vì câu trả lời chi tiết như vậy
Salman

168
Đối với những người không biết, tôi nghĩ tôi sẽ đề cập rằng Tom là đồng tác giả của "Lập trình Perl" (còn gọi là cuốn sách Lạc đà) và là một trong những cơ quan hàng đầu của Perl. Nếu bạn nghi ngờ rằng đây là Tom Christiansen thực sự, hãy quay lại và đọc bài viết.
Bill Ruppert

20
Tóm lại: RegEx's được đặt tên sai. Tôi nghĩ đó là một sự xấu hổ, nhưng nó sẽ không thay đổi. Các công cụ 'RegEx' tương thích không được phép từ chối các ngôn ngữ không thông thường. Do đó, chúng không thể được thực hiện chính xác chỉ với Máy nhà nước Finte. Các khái niệm mạnh mẽ xung quanh các lớp tính toán không được áp dụng. Việc sử dụng RegEx không đảm bảo thời gian thực hiện O (n). Ưu điểm của RegEx là cú pháp ngắn gọn và miền ngụ ý nhận dạng ký tự. Đối với tôi, đây là một con tàu đắm di chuyển chậm, không thể rời mắt, nhưng với những hậu quả khủng khiếp đang diễn ra.
Steve Steiner

27
@tchrist, điều này không bao giờ trả lời câu hỏi ban đầu của OP. Và phân tích thuật ngữ thích hợp ở đây? Afaics regex đang thực hiện phân tích tokenizing / từ vựng, nhưng phân tích cú pháp cuối cùng được thực hiện với mã Perl, chứ không phải chính regex.
Qtax

65
@tchrist Rất ấn tượng. Bạn rõ ràng là một lập trình viên Perl có tay nghề cao và tài năng, và cực kỳ am hiểu về các biểu thức chính quy hiện đại. Tuy nhiên, tôi sẽ chỉ ra rằng những gì bạn đã viết không thực sự là một biểu thức chính quy (hiện đại, thường xuyên, hay nói cách khác), mà là một chương trình Perl sử dụng các biểu thức chính quy rất nhiều. Bài đăng của bạn có thực sự hỗ trợ cho tuyên bố rằng các biểu thức thông thường có thể phân tích chính xác HTML không? Hay nó giống như bằng chứng cho thấy Perl có thể phân tích HTML chính xác? Dù bằng cách nào, công việc tốt đẹp!
Mike Clark

126
  1. Bạn có thể viết một cuốn tiểu thuyết như tchrist đã làm
  2. Bạn có thể sử dụng thư viện DOM, tải HTML và sử dụng xpath và chỉ cần sử dụng //input[@type="hidden"]. Hoặc nếu bạn không muốn sử dụng xpath, chỉ cần lấy tất cả các đầu vào và bộ lọc ẩn getAttribute.

Tôi thích # 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>';
}

Kết quả:

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

72
Đó thực sự là quan điểm của tôi. Tôi muốn cho thấy nó khó như thế nào.
tchrist

19
Công cụ rất tốt đó. Tôi đã thực sự hy vọng mọi người sẽ cho thấy việc sử dụng một lớp phân tích cú pháp dễ dàng hơn bao nhiêu, cảm ơn! Tôi chỉ muốn một ví dụ hoạt động về những rắc rối cực độ mà bạn phải trải qua để làm điều đó từ đầu bằng cách sử dụng regexes. Tôi chắc chắn hy vọng hầu hết mọi người kết luận sử dụng trình phân tích cú pháp prefab trên HTML chung thay vì tự lăn. Mặc dù vậy, Regexes vẫn tuyệt vời cho HTML đơn giản do chính họ tạo ra, vì điều đó đã loại bỏ 99,98% độ phức tạp.
tchrist

5
Điều tuyệt vời sau khi đọc 2 cách tiếp cận rất thú vị này sẽ là so sánh tốc độ / mức sử dụng bộ nhớ / CPU của một cách tiếp cận với cách tiếp cận khác (tức là lớp phân tích cú pháp VS dựa trên regex).
the_yellow_logo

1
@ Avt'W Vâng, không phải là bạn nên viết một cuốn 'tiểu thuyết' nếu Regexes xảy ra nhanh hơn, nhưng thực tế nó sẽ thực sự thú vị khi biết. :) Nhưng tôi đoán là, một trình phân tích cú pháp cũng mất ít tài nguyên hơn ..
Dennis98

Đây thực sự là lý do tại sao XPath được phát minh ngay từ đầu!
Thorbjørn Ravn Andersen

21

Theo tinh thần của giải pháp từ vựng của Tom Christiansen, đây là một liên kết đến bài viết dường như bị lãng quên năm 1998 của Robert Cameron, REX: XML Shallow Parsing với các biểu thức chính quy.

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

trừu tượng

Cú pháp của XML đủ đơn giản để có thể phân tích một tài liệu XML thành một danh sách các mục đánh dấu và các mục văn bản của nó bằng một biểu thức chính quy duy nhất. Việc phân tích cú pháp nông như vậy của một tài liệu XML có thể rất hữu ích cho việc xây dựng nhiều công cụ xử lý XML nhẹ. Tuy nhiên, các biểu thức chính quy phức tạp có thể khó xây dựng và thậm chí khó đọc hơn. Sử dụng một hình thức lập trình biết chữ cho các biểu thức chính quy, bài viết này ghi lại một tập hợp các biểu thức phân tích cú pháp nông XML có thể được sử dụng làm cơ sở cho phân tích cú pháp nông XML đơn giản, chính xác, hiệu quả, mạnh mẽ và độc lập với ngôn ngữ. Hoàn thành triển khai trình phân tích cú pháp nông dưới 50 dòng trong Perl, JavaScript và Lex / Flex cũng được đưa ra.

Nếu bạn thích đọc về các biểu thức thông thường, bài viết của Cameron rất hấp dẫn. Bài viết của ông súc tích, kỹ lưỡng, và rất chi tiết. Anh ta không chỉ đơn giản chỉ cho bạn cách xây dựng biểu thức chính quy REX mà còn là cách tiếp cận để xây dựng bất kỳ biểu thức phức tạp nào từ các phần nhỏ hơn.

Tôi đã sử dụng và tắt biểu thức chính quy REX trong 10 năm để giải quyết loại vấn đề mà người đăng ban đầu đã hỏi về (làm cách nào để khớp với thẻ cụ thể này nhưng không phải là một thẻ rất giống nhau khác?). Tôi đã tìm thấy regex anh ấy phát triển là hoàn toàn đáng tin cậy.

REX đặc biệt hữu ích khi bạn tập trung vào các chi tiết từ vựng của tài liệu - ví dụ: khi chuyển đổi một loại tài liệu văn bản (ví dụ: văn bản thuần, XML, SGML, HTML) sang tài liệu khác, trong đó tài liệu có thể không hợp lệ, hình thành tốt, hoặc thậm chí có thể phân tích cú pháp cho hầu hết các chuyển đổi. Nó cho phép bạn nhắm mục tiêu các đảo đánh dấu ở bất cứ đâu trong tài liệu mà không làm phiền phần còn lại của tài liệu.


7

Mặc dù tôi thích nội dung của những câu trả lời còn lại, nhưng họ không thực sự trả lời câu hỏi trực tiếp hoặc chính xác. Ngay cả câu trả lời của Platinum cũng quá phức tạp và cũng kém hiệu quả hơn. Vì vậy, tôi đã buộc phải đặt điều này.

Tôi là một người ủng hộ Regex rất lớn, khi được sử dụng một cách chính xác. Nhưng vì sự kỳ thị (và hiệu suất), tôi luôn tuyên bố rằng XML hoặc HTML được định dạng tốt nên sử dụng Trình phân tích cú pháp XML. Và hiệu năng thậm chí tốt hơn sẽ là phân tích cú pháp chuỗi, mặc dù có một ranh giới giữa khả năng đọc nếu điều đó quá tầm tay. Tuy nhiên, đó không phải là câu hỏi. Câu hỏi là làm thế nào để khớp với thẻ đầu vào loại ẩn. Câu trả lời là:

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

Tùy thuộc vào hương vị của bạn, tùy chọn regex duy nhất bạn cần đưa vào là tùy chọn ignorecase.


5
<input type='hidden' name='Oh, <really>?' value='Try a real HTML parser instead.'>
Ilmari Karonen

4
Ví dụ của bạn là tự đóng cửa. Nên kết thúc bằng />. Ngoài ra, trong khi cơ hội có một >trường tên gần như không có, thì thực sự có thể có >một tay cầm hành động. EG: Cuộc gọi javascript nội tuyến trên thuộc tính OnClick. Điều đó đang được nói, tôi có một trình phân tích cú pháp XML cho những người đó, nhưng cũng có một Regex cho những nơi mà tài liệu tôi đưa ra quá rối rắm để các trình phân tích cú pháp XML xử lý, nhưng Regex thì có thể. Ngoài ra, đây không phải là câu hỏi. Bạn sẽ không bao giờ gặp phải những tình huống này với một đầu vào ẩn và câu trả lời của tôi là tốt nhất. Ya, <really>!.
Suamere

3
/>là một ism XML; nó không bắt buộc trong bất kỳ phiên bản HTML nào, ngoại trừ XHTML (vốn không bao giờ thực sự đạt được nhiều lực kéo và đã được thay thế bởi HTML5). Và bạn đúng rằng có rất nhiều HTML không thực sự hợp lệ ngoài kia, nhưng một trình phân tích cú pháp HTML ( không phải XML) tốt sẽ có thể đối phó với hầu hết các HTML đó; nếu họ không, nhiều khả năng sẽ không trình duyệt.
Ilmari Karonen

1
Nếu việc phân tích hoặc tìm kiếm duy nhất bạn cần là một lần nhấn duy nhất để trả về một tập hợp các trường nhập liệu ẩn, biểu thức chính quy này sẽ hoàn hảo. Sử dụng (các) lớp Tài liệu XML .NET hoặc tham chiếu Trình phân tích cú pháp XML / HTML của bên thứ ba chỉ để gọi một phương thức sẽ là quá mức khi Regex được xây dựng. Và bạn có quyền rằng một trang web đã nhầm lẫn rằng một HTML tốt trình phân tích cú pháp không thể xử lý nó có lẽ thậm chí không phải là thứ mà một nhà phát triển sẽ nhìn vào. Nhưng công ty của tôi được trao hàng triệu trang mỗi tháng được nối và ghép theo nhiều cách mà đôi khi (không phải lúc nào cũng vậy), Regex là lựa chọn tốt nhất.
Suamere

1
Điểm duy nhất là chúng tôi không chắc chắn về toàn bộ lý do công ty phát triển này muốn câu trả lời này. Nhưng đó là những gì anh ấy yêu cầu.
Suamere

3

bạn có thể thử điều này:

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

và để có kết quả gần hơn, bạn có thể thử điều này:

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

bạn có thể kiểm tra mẫu regex của mình tại đây http://regapal.com/

những pattens này là tốt cho việc này:

<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" />

và theo thứ tự ngẫu nhiên type, namevaluebạn có thể sử dụng điều này:

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

hoặc là

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

về điều này:

<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" />

`

bằng cách này, tôi nghĩ rằng bạn muốn một cái gì đó như thế này:

<[ ]*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"[ ]*)+)[ ]*/>

Nó không tốt nhưng nó hoạt động theo bất kỳ cách nào.

kiểm tra nó trong: http://regapidal.com/


1

Tôi muốn sử dụng **DOMDocument**để trích xuất mã 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, bạn có thể kiểm tra nó tại đây - regex101.com. Nó cho thấy kết quả ở thời gian thực. Một số quy tắc về Regapi: http://www.eclipse.org/tptp/home/doads/installguide/gla_42/ref/rregapi.html Reader .


0

giả sử nội dung html của bạn được lưu trữ trong chuỗi html sau đó để có được mọi đầu vào có chứa kiểu ẩn, bạn có thể sử dụng biểu thức chính quy

var regex = /(<input.*?type\s?=\s?["']hidden["'].*?>)/g;
html.match(regex);

regex ở trên tìm thấy <inputtheo sau bởi bất kỳ số lượng ký tự nào cho đến khi nó được type="hidden"hoặc gõ = 'hidden' theo sau bởi bất kỳ số lượng ký tự nào cho đến khi nó nhận được>

/ g nói biểu thức chính quy để tìm mọi chuỗi con khớp với mẫu đã cho.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.