2008-08-04 20 views
41

Tengo un archivo en el siguiente formato:Regex: Para sacar una subcadena entre dos etiquetas en una cadena

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

me gustaría agarrar el Data I want de entre las etiquetas [Start] y utilizando [End] un Regex. ¿Alguien puede mostrarme cómo se puede hacer esto?

+1

Imagen similar a "expresiones regulares para obtener el texto dentro de las etiquetas" - http://stackoverflow.com/questions/353309/regex-to-get-text-within-tags –

Respuesta

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

Esto debería de esperar que soltar los [start] y [end] marcadores también.

+2

El futuro puede ser menos eficiente, pero me gusta cómo evitó que se rompa si hay un inesperado '[inicio]' o '[fin]'. Siempre es bueno pensar en casos límite y adelantarse a ellos. –

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

Zhich pondrá el texto en el medio dentro de una captura.

+2

Mucho mejor (más simple) que la respuesta aceptada ... :-) – PhiLho

+6

Esto todavía no capturará cadenas que tengan saltos de línea – Doug

+2

@Doug use option dotall. No es un problema de la expresión regular. – AlexR

1

Con Perl puede rodear los datos que desea con() y extraerlos más tarde, quizás otros idiomas tengan una función similar.

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

Una discusión más completa de los peligros del uso de una expresión regular para encontrar etiquetas a juego se puede encontrar en: http://faq.perl.org/perlfaq4.html#How_do_I_find_matchi. En particular, tenga en cuenta que las etiquetas de anidamiento realmente necesitan un analizador completo para poder interpretarlo correctamente.

Tenga en cuenta que la sensibilidad entre mayúsculas y minúsculas deberá desactivarse para responder a la pregunta tal como se establece. En Perl, que es el modificador i:

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

El otro truco es utilizar el *? cuantificador que desactiva la codicia de la coincidencia capturada. Por ejemplo, si tiene una que no encaja, [final] etiqueta:

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

es probable que no desea capturar:

Data i want [End] Data 
4

Aunque se puede usar una expresión regular para analizar la datos entre las etiquetas de apertura y cierre, debe pensar detenidamente si esta es una ruta que desea bajar. La razón de esto es el potencial de las etiquetas para anidar: si las etiquetas de anidación podrían ocurrir alguna vez, el lenguaje ya no es regular y las expresiones regulares dejan de ser la herramienta adecuada para analizarlo.

Muchas implementaciones de expresiones regulares, como PCRE o las expresiones regulares de perl, admiten la retro-localización que se puede usar para lograr este efecto aproximado. Pero PCRE (a diferencia de perl) no es compatible con backtracking ilimitado, y esto puede hacer que las cosas se rompan de manera extraña tan pronto como tenga demasiadas etiquetas.

Hay una entrada en el blog muy comúnmente citado que trata sobre esto más, http://kore-nordmann.de/blog/do_NOT_parse_using_regexp.html (Google para ello y comprobar la memoria caché en la actualidad, que parecen estar teniendo un tiempo de inactividad)

3

Bueno, si usted garantiza que cada puesta en marcha es seguido etiqueta por una etiqueta final, entonces lo siguiente funcionaría.

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

Sin embargo, si usted tiene un texto complejo como el follwoing:

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

allí tendría que tener problemas con expresiones regulares.

Ahora el siguiente ejemplo se retirarán todos los enlaces activos en una página:

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

En el caso anterior podemos garantizar que no habría ningún caso anidados de:

'<a></a>' 

Entonces, esta es una pregunta compleja y no se puede resolver simplemente con una respuesta simple.

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

tuve un problema similar durante un tiempo & te puedo decir que este método funciona ...

0

lectura del texto con entre corchetes [], es decir, [Inicio] y [Fin], y valide la matriz con una lista de valores. 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; 
} 
Cuestiones relacionadas