Regex:Para extrair uma substring entre duas tags em uma string
Pergunta
Tenho um arquivo no seguinte formato:
Data Data Data [Start] Data I want [End] Data
Eu gostaria de pegar o Data I want
entre o [Start]
e [End]
tags usando um Regex.Alguém pode me mostrar como isso pode ser feito?
Solução
\[start\]\s*(((?!\[start\]|\[end\]).)+)\s*\[end\]
Esperançosamente, isso deve derrubar o [start]
e [end]
marcadores também.
Outras dicas
\[start\](.*?)\[end\]
Zhich colocará o texto no meio de uma captura.
$text ="Data Data Data start Data i want end Data";
($content) = $text =~ m/ start (.*) end /;
print $content;
Eu tive um problema semelhante por um tempo e posso dizer que esse método funciona ...
Uma discussão mais completa sobre as armadilhas do uso de uma regex para encontrar tags correspondentes pode ser encontrada em: http://faq.perl.org/perlfaq4.html#How_do_I_find_matchi.Em particular, esteja ciente de que as tags de aninhamento realmente precisam de um analisador completo para serem interpretadas corretamente.
Observe que a distinção entre maiúsculas e minúsculas precisará ser desativada para responder à pergunta conforme indicado.Em perl, esse é o eu modificador:
$ echo "Data Data Data [Start] Data i want [End] Data" \
| perl -ne '/\[start\](.*?)\[end\]/i; print "$1\n"'
Data i want
O outro truque é usar o *? quantificador que desativa a ganância da partida capturada.Por exemplo, se você tiver um não correspondente [fim] marcação:
Data Data [Start] Data i want [End] Data [end]
você provavelmente não deseja capturar:
Data i want [End] Data
Embora você possa usar uma expressão regular para analisar os dados entre as tags de abertura e fechamento, você precisa pensar muito se esse é o caminho que deseja seguir.A razão para isso é o potencial de aninhamento das tags:se tags de aninhamento puderem acontecer ou acontecerem, diz-se que a linguagem não é mais regular e as expressões regulares deixam de ser a ferramenta adequada para analisá-la.
Muitas implementações de expressões regulares, como PCRE ou expressões regulares do Perl, suportam retrocesso que pode ser usado para obter esse efeito aproximado.Mas o PCRE (ao contrário do Perl) não suporta retrocesso ilimitado, e isso pode realmente fazer com que as coisas quebrem de maneiras estranhas assim que você tiver muitas tags.
Há uma postagem de blog muito citada que discute mais isso, http://kore-nordmann.de/blog/do_NOT_parse_using_regexp.html (pesquise no Google e verifique o cache atualmente, eles parecem estar tendo algum tempo de inatividade)
Bem, se você garantir que cada tag inicial seja seguida por uma tag final, o seguinte funcionaria.
\[start\](.*?)\[end\]
No entanto, se você tiver um texto complexo como o seguinte:
[start] sometext [start] sometext2 [end] sometext [end]
então você teria problemas com regex.
Agora, o exemplo a seguir extrairá todos os links importantes de uma página:
'/<a(.*?)a>/i'
No caso acima podemos garantir que não haveria casos aninhados de:
'<a></a>'
Portanto, esta é uma questão complexa e não pode ser resolvida apenas com uma resposta simples.
Com Perl você pode cercar os dados que deseja com () e retirá-los mais tarde, talvez outras linguagens tenham um recurso semelhante.
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
}
Consulte esta pergunta para extrair texto entre tags com caracteres de espaço e pontos (.
)
[\S\s]
é o que eu usei
Regex para corresponder a qualquer caractere, incluindo novas linhas
Lendo o texto entre colchetes [], ou seja, [Início] e [Fim] e valide o array com uma lista de valores. jsfiddle http://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;
}