2008-08-04 28 views
41

Tôi có một tập tin theo định dạng sau:Regex: Để kéo ra một tiểu chuỗi giữa hai thẻ trong một chuỗi

 
Data Data 
Data 
[Start] 
Data I want 
[End] 
Data 

Tôi muốn lấy Data I want từ giữa [Start][End] thẻ sử dụng một Regex. Bất cứ ai có thể cho tôi thấy làm thế nào điều này có thể được thực hiện?

+1

tương tự như "RegEx để có được văn bản trong thẻ" - http://stackoverflow.com/questions/353309/regex-to-get-text-within-tags –

Trả lời

21
\[start\]\s*(((?!\[start\]|\[end\]).)+)\s*\[end\] 

Điều này hy vọng cũng sẽ đánh dấu các dấu mốc [start][end].

+2

Nhìn về phía trước có thể kém hiệu quả hơn nhưng tôi thích cách bạn ngăn nó phá vỡ nếu có một '[bắt đầu]' hoặc '[cuối] không mong đợi'. Nó luôn luôn là tốt để suy nghĩ về trường hợp cạnh và preempt chúng. –

62
\[start\](.*?)\[end\] 

Zhich'll đặt văn bản ở giữa trong quá trình chụp.

+2

Tốt hơn nhiều (đơn giản) so với câu trả lời được chấp nhận ... :-) – PhiLho

+6

Điều này vẫn không bắt được các chuỗi có ngắt dòng – Doug

+2

@Doug tùy chọn sử dụng dotall. Không phải là một vấn đề của regex. – AlexR

1

Với Perl bạn có thể bao quanh dữ liệu bạn muốn bằng() và kéo nó ra sau, có lẽ các ngôn ngữ khác có tính năng tương tự.

if ($s_output =~ /(data data data data START(data data data)END (data data)/) 
{ 
    $dataAllOfIt = $1;  # 1 full string 
    $dataInMiddle = $2;  # 2 Middle Data 
    $dataAtEnd = $3;  # 3 End Data 
} 
4

Thảo luận đầy đủ hơn về các cạm bẫy sử dụng regex để tìm thẻ phù hợp có thể tìm thấy tại: http://faq.perl.org/perlfaq4.html#How_do_I_find_matchi. Đặc biệt, hãy lưu ý rằng các thẻ lồng nhau thực sự cần một trình phân tích cú pháp chính thức để được diễn giải một cách chính xác.

Lưu ý rằng cần phải tắt tính nhạy cảm của trường hợp để trả lời câu hỏi như đã nêu. Trong perl, đó là i modifier:

$ echo "Data Data Data [Start] Data i want [End] Data" \ 
    | perl -ne '/\[start\](.*?)\[end\]/i; print "$1\n"' 
Data i want 

Bí quyết khác là sử dụng *? định lượng sẽ tắt tính tham lam của trận đấu bị bắt. Ví dụ, nếu bạn có một tổ chức phi phù hợp với [cuối] tag:

Data Data [Start] Data i want [End] Data [end] 

có thể bạn không muốn chụp:

Data i want [End] Data 
4

Trong khi bạn có thể sử dụng một biểu thức chính quy để phân tích dữ liệu giữa các thẻ mở và đóng, bạn cần suy nghĩ thật lâu và khó để biết đây có phải là con đường bạn muốn đi xuống hay không. Lý do cho nó là tiềm năng của các thẻ để lồng: nếu các thẻ lồng nhau có thể xảy ra hoặc có thể xảy ra, ngôn ngữ được cho là không còn thường xuyên và các biểu thức chính quy không còn là công cụ thích hợp để phân tích nó.

Nhiều triển khai biểu thức chính quy, chẳng hạn như biểu thức chính quy của PCRE hoặc perl, hỗ trợ phát lại có thể được sử dụng để đạt được hiệu ứng thô này. Nhưng PCRE (không giống như perl) không hỗ trợ backtracking không giới hạn, và điều này thực sự có thể khiến mọi thứ phá vỡ theo những cách kỳ lạ ngay sau khi bạn có quá nhiều thẻ.

Có một bài viết trên blog rất thường được trích dẫn rằng thảo luận này hơn, http://kore-nordmann.de/blog/do_NOT_parse_using_regexp.html (google cho nó và kiểm tra bộ nhớ cache hiện nay, họ dường như có một số thời gian chết)

3

Vâng, nếu bạn đảm bảo rằng mỗi bắt đầu từ khóa được theo sau bằng một thẻ kết thúc, sau đó thẻ sẽ hoạt động.

\[start\](.*?)\[end\] 

Tuy nhiên, nếu bạn có văn bản phức tạp như follwoing:

[start] sometext [start] sometext2 [end] sometext [end] 

sau đó bạn sẽ gặp vấn đề với regex.

Bây giờ ví dụ sau sẽ rút khỏi tất cả các liên kết nóng trong một trang:

'/<a(.*?)a>/i' 

Trong trường hợp trên chúng ta có thể đảm bảo rằng sẽ không có bất kỳ trường hợp lồng nhau của:

'<a></a>' 

Vì vậy, đây là một câu hỏi phức tạp và không thể chỉ được giải quyết bằng một câu trả lời đơn giản.

5
$text ="Data Data Data start Data i want end Data"; 
($content) = $text =~ m/ start (.*) end /; 
print $content; 

Tôi đã có một vấn đề tương tự trong một thời gian & tôi có thể cho bạn biết phương pháp này hoạt động ...

0

Đọc văn bản với dấu ngoặc vuông [] tức là [Bắt đầu] và [Kết thúc] và xác thực mảng bằng danh sách giá trị. jsfiddlehttp://jsfiddle.net/muralinarisetty/r4s4wxj4/1/

var mergeFields = ["[sitename]", 
        "[daystoholdquote]", 
        "[expires]", 
        "[firstname]", 
        "[lastname]", 
        "[sitephonenumber]", 
        "[hoh_firstname]", 
        "[hoh_lastname]"];  

var str = "fee [sitename] [firstname] \ 
sdfasd [lastname] "; 
var res = validateMeargeFileds(str); 
console.log(res); 

function validateMeargeFileds(input) { 
    var re = /\[\w+]/ig; 
    var isValid; 
    var myArray = input.match(re); 

    try{ 
     if (myArray.length > 0) { 
      myArray.forEach(function (field) { 

       isValid = isMergeField(field); 

       if (!isValid){ 
        throw e;       
       } 
      }); 
     } 
    } 
    catch(e) {   
    } 

    return isValid; 
} 

function isMergeField(mergefield) { 
    return mergeFields.indexOf(mergefield.toLowerCase()) > -1; 
} 
Các vấn đề liên quan