2008-08-04 13 views
41

ich in folgendem Format eine Datei habe herausziehen:Regex: Um eine Unterkette zwischen zwei Tags in einer Zeichenfolge

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

Ich mag die Data I want zwischen den [Start] und [End] Tags greifen mit ein Regex. Kann mir jemand zeigen, wie das geht?

+1

Similiar zu "RegEx Text innerhalb von Tags zu bekommen" - http://stackoverflow.com/questions/353309/regex-to-get-text-within-tags –

Antwort

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

Dies sollte auch den [start] und [end] Marker hoffentlich fallen.

+2

Der Blick nach vorne mag weniger effizient sein, aber ich mag es, wie Sie verhindert haben, dass es bricht, wenn es ein unerwartetes '[start]' oder '[end]' gibt. Es ist immer gut, über Randfälle nachzudenken und ihnen vorzubeugen. –

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

Zhich'll den Text in der Mitte in einem Capture.

+2

Viel besser (einfacher) als die akzeptierte Antwort ... :-) – PhiLho

+6

Dies wird immer noch keine Zeichenketten fangen, die Zeilenumbrüche haben – Doug

+2

@Doug verwenden Option dotall. Kein Problem der Regex. – AlexR

1

Mit Perl können Sie die gewünschten Daten mit() 's umgeben und später herausziehen, vielleicht haben andere Sprachen eine ähnliche Funktion. http://faq.perl.org/perlfaq4.html#How_do_I_find_matchi:

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

Eine vollständigere Erörterung der Gefahren eines regex passende Tags finden finden Sie unter. Beachten Sie insbesondere, dass Schachtelungs-Tags wirklich einen vollwertigen Parser benötigen, um richtig interpretiert zu werden.

Beachten Sie, dass die Groß- und Kleinschreibung ignoriert werden muss, um die gestellte Frage zu beantworten. In Perl, das ist die i Modifikator:

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

Der andere Trick ist, die * zu benutzen? Quantifizierer, der die Gierigkeit des eingefangenen Spiels abstellt. wenn Sie eine nicht-passende [Ende] Tag Zum Beispiel:

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

Sie wollen wahrscheinlich nicht erfassen:

Data i want [End] Data 
4

Während Sie einen regulären Ausdruck verwenden können, um das Parsen Daten zwischen öffnenden und schließenden Tags müssen Sie lange und gründlich darüber nachdenken, ob dies ein Pfad ist, den Sie ablegen möchten. Der Grund dafür ist das Potenzial von Tags zum Verschachteln: Wenn Verschachtelungs-Tags jemals vorkommen oder jemals passieren könnten, wird gesagt, dass die Sprache nicht mehr regulär ist und reguläre Ausdrücke nicht mehr das richtige Werkzeug zum Parsen sind.

Viele Implementierungen für reguläre Ausdrücke, z. B. PCRE oder die regulären Ausdrücke von Perl, unterstützen Backtracking, mit dem dieser grobe Effekt erzielt werden kann. Aber PCRE (im Gegensatz zu Perl) unterstützt kein unbegrenztes Backtracking, und dies kann tatsächlich dazu führen, dass die Dinge auf seltsame Weise abbrechen, sobald Sie zu viele Tags haben.

Es ist eine sehr häufig zitierten Blog-Post, die diese mehr diskutiert, http://kore-nordmann.de/blog/do_NOT_parse_using_regexp.html (für sie Google und den Cache zur Zeit prüfen, scheinen sie eine Auszeit zu haben)

3

Nun, wenn Sie garantieren, dass jedes Start-Tag folgt Mit einem End-Tag würde das Folgende funktionieren.

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

jedoch Wenn Sie komplexen Text wie der follwoing haben:

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

dann würden Sie Probleme mit Regex laufen.

nun das folgende Beispiel ziehen alle heißen Links in einer Seite:

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

Im obigen Fall können wir garantieren, dass es keine verschachtelten Fälle wäre:

'<a></a>' 

Also, das ist eine komplexe Frage und kann nicht einfach mit einer einfachen Antwort gelöst werden.

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

Ich hatte ein ähnliches Problem für eine Weile & ich Ihnen diese Methode sagen kann, funktioniert ...

0

den Text zu lesen verwendet mit in eckigen Klammern [], d. h. [Start] und [Ende] und validiere das Array mit einer Liste von Werten. 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; 
}