regex todas Como faço para combinar qualquer caractere em várias linhas em uma expressão regular?




regex js (17)

Por exemplo, esse regex

(.*)<FooBar>

vai combinar:

abcde<FooBar>

Mas como faço para combinar em várias linhas?

abcde
fghij<FooBar>

Answer #1
/(.*)<FooBar>/s

o s faz com que o ponto (.) corresponda a retornos de carro


Answer #2

Geralmente, precisamos modificar uma substring com algumas palavras-chave espalhadas pelas linhas que precedem a substring. Considere um elemento xml:

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>81</PercentComplete>
</TASK>

Suponha que queremos modificar o 81, para algum outro valor, digamos 40. Primeiro, identifique .UID.21..UID. , pule todos os caracteres, incluindo \n até .PercentCompleted. . O padrão de expressão regular e a especificação de substituição são:

String hw = new String("<TASK>\n  <UID>21</UID>\n  <Name>Architectural design</Name>\n  <PercentComplete>81</PercentComplete>\n</TASK>");
String pattern = new String ("(<UID>21</UID>)((.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
String replaceSpec = new String ("$1$2$440$6");
//note that the group (<PercentComplete>) is $4 and the group ((.|\n)*?) is $2.

String  iw = hw.replaceFirst(pattern, replaceSpec);
System.out.println(iw);

<TASK>
  <UID>21</UID>
  <Name>Architectural design</Name>
  <PercentComplete>40</PercentComplete>
</TASK>

O subgrupo (.|\n) é provavelmente o grupo ausente $3 . Se fizermos isso não capturando por (?:.|\n) então o $3 é (<PercentComplete>) . Então o padrão e replaceSpec também podem ser:

pattern = new String("(<UID>21</UID>)((?:.|\n)*?)(<PercentComplete>)(\\d+)(</PercentComplete>)");
replaceSpec = new String("$1$2$340$5")

e a substituição funciona corretamente como antes.


Answer #3

Para o Eclipse funcionou após a expressão:

Foo

Bar Jadajada "

Expressão regular:

Foo[\S\s]{1,10}.*Bar*

Answer #4

"." normalmente não corresponde a quebras de linha. A maioria dos mecanismos de regex permite que você adicione o S flag (também chamado DOTALL e SINGLELINE ) para fazer "." também coincide com novas linhas. Se isso falhar, você pode fazer algo como [\S\s] .


Answer #5

Em JavaScript, use /[\S\s]*<Foobar>/ . source


Answer #6

Depende da linguagem, mas deve haver um modificador que você possa adicionar ao padrão de expressão regular. No PHP é:

/(.*)<FooBar>/s

O s no final faz com que o ponto corresponda a todos os caracteres, incluindo novas linhas.


Answer #7

No contexto de uso dentro de idiomas, expressões regulares agem em strings, não em linhas. Então você deve ser capaz de usar o regex normalmente, assumindo que a string de entrada tenha várias linhas.

Nesse caso, a regex dada corresponderá à string inteira, já que "<FooBar>" está presente. Dependendo das especificidades da implementação da regex, o valor de $ 1 (obtido de "(. *)") Será "fghij" ou "abcde \ nfghij". Como outros já disseram, algumas implementações permitem controlar se o "." irá coincidir com a nova linha, dando-lhe a escolha.

O uso da expressão regular baseada em linha geralmente é para itens de linha de comando como egrep.


Answer #8

A questão é, pode . padrão combina com qualquer personagem? A resposta varia de motor para motor. A principal diferença é se o padrão é usado por uma biblioteca regex POSIX ou não POSIX.

Nota especial sobre lua-patterns : eles não são considerados expressões regulares, mas . corresponde a qualquer caractere, mesmo que os mecanismos baseados em POSIX.

Outra nota em matlab e octave : o . corresponde a qualquer char por padrão ( demo ): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match'); str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match'); (os tokens contêm um item abcde\n fghij ).

Além disso, em todas as gramáticas regex do boost , o ponto corresponde às quebras de linha por padrão. A gramática do ECMAScript do Boost permite que você desligue isto com regex_constants::no_mod_m ( source ).

Quanto ao oracle (é baseado em POSIX), use a opção n ( demo ): select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual

Motores baseados em POSIX :

Um mero . já coincide com quebras de linha, não há necessidade de usar nenhum modificador, veja bash ( demo ).

O tcl ( demo ), postgresql ( demo ), r (TRE, base do motor padrão R sem perl=TRUE , para base R com perl=TRUE ou para padrões stringr / stringi , usa o modificador inline (?s) ) ( demo ) também tratar . o mesmo caminho.

No entanto , a maioria das ferramentas baseadas em POSIX processam a entrada linha por linha. Portanto, não corresponde às quebras de linha apenas porque elas não estão no escopo. Aqui estão alguns exemplos de como sobrescrever isso:

  • sed - Existem várias soluções alternativas, a mais precisa mas não muito segura é sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/' sed 'H;1h;$!d;x; s/\(.*\)><Foobar>/\1/' ( H;1h;$!d;x; coloca o arquivo na memória). Se linhas inteiras devem ser incluídas, sed '/start_pattern/,/end_pattern/d' file (a remoção do início terminará com linhas combinadas incluídas) ou sed '/start_pattern/,/end_pattern/{{//!d;};}' file (com linhas de correspondência excluídas) pode ser considerado.
  • perl - perl -0pe 's/(.*)<FooBar>/$1/gs' <<< "$str" ( -0 copia o arquivo inteiro para a memória, -p imprime o arquivo depois de aplicar o script dado por -e ). Note que usar -000pe irá fazer o slurp do arquivo e ativar o 'modo de parágrafo' onde o Perl usa novas linhas consecutivas ( \n\n ) como o separador de registro.
  • gnu-grep - grep -Poz '(?si)abc\K.*?(?=<Foobar>)' file . Aqui, z ativa o slurping de arquivo, (?s) ativa o modo DOTALL para o arquivo . padrão, (?i) ativa o modo insensível a maiúsculas e minúsculas, \K omite o texto correspondido até agora, *? é um quantificador preguiçoso, (?=<Foobar>) corresponde ao local antes de <Foobar> .
  • pcregrep - pcregrep -Mi "(?si)abc\K.*?(?=<Foobar>)" file ( M habilita o arquivo slurping aqui). Nota O pcregrep é uma boa solução para usuários do Mac OS grep .

Veja demos .

Mecanismos não baseados em POSIX :

  • php - Use s modificador modificador PCRE_DOTALL : preg_match('~(.*)<Foobar>~s', $s, $m) ( demo )
  • c# - Use o sinalizador RegexOptions.Singleline ( demo ):
    - var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
    - var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
  • powershell - Use (?s) opção inline: $s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1] $s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
  • perl - Use s modificador s (ou (?s) versão inline no início) ( demo ): /(.*)<FooBar>/s
  • python - Use re.DOTALL (ou re.S ) sinalizadores ou (?s) modificador m = re.search(r"(.*)<FooBar>", s, flags=re.S) demo ): m = re.search(r"(.*)<FooBar>", s, flags=re.S) ( e então if m: print(m.group(1)) )
  • java - Use o modificador Pattern.DOTALL (ou sinalizador inline (?s) ) ( demo ): Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
  • groovy - Use (?s) no modificador padrão ( demo ): regex = /(?s)(.*)<FooBar>/
  • scala - Use (?s) modificador ( demo ): "(?s)(.*)<Foobar>".r.findAllIn("abcde\n fghij<Foobar>").matchData foreach { m => println(m.group(1)) }
  • javascript - Use [^] ou soluções alternativas [\d\D] / [\w\W] / [\s\S] ( demo ): s.match(/([\s\S]*)<FooBar>/)[1]
  • c ++ ( std::regex ) Use [\s\S] ou as soluções alternativas JS ( demo ): regex rex(R"(([\s\S]*)<FooBar>)");
  • vba - Use a mesma abordagem que em JavaScript, ([\s\S]*)<Foobar> .
  • ruby - Use /m modificador MULTILINE ( demo ): s[/(.*)<Foobar>/m, 1]
  • go go - Use o modificador inline (?s) no início ( demo ): re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
  • swift - Use dotMatchesLineSeparators ou (mais fácil) passe o modificador in-line (?s) para o padrão: let rx = "(?s)(.*)<Foobar>"
  • objective-c - O mesmo que Swift, (?s) funciona mais NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError]; , mas aqui está como a opção pode ser usada : NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];
  • re2 , google-apps-script google-apps-script - Use (?s) modificador ( demo ): "(?s)(.*)<Foobar>" (no Google Spreadsheets, =REGEXEXTRACT(A2,"(?s)(.*)<Foobar>") )

NOTAS SOBRE (?s) :

Na maioria dos mecanismos não POSIX, o modificador inline (?s) (ou opção de sinalizador incorporado) pode ser usado para impor . para coincidir com quebras de linha.

Se colocado no início do padrão, (?s) altera o comportamento de todos . no padrão. Se o (?s) é colocado em algum lugar após o começo, somente aqueles . serão afetados que estão localizados à direita dele, a menos que este seja um padrão passado para o Python re . No Python re , independentemente da localização (?s) , todo o padrão . são afetados. O efeito (?s) é interrompido usando (?-s) . Um grupo modificado pode ser usado para afetar somente um intervalo especificado de um padrão regex (por exemplo, Delim1(?s:.*?)\nDelim2.* Fará a primeira .*? Delim1(?s:.*?)\nDelim2.* entre as novas linhas e a segunda .* Delim1(?s:.*?)\nDelim2.* apenas à resto da linha).

Nota POSIX :

Em mecanismos que não são de expressão regular, para corresponder a qualquer caractere, as construções [\s\S] / [\d\D] / [\w\W] podem ser usadas.

Em POSIX, [\s\S] não está combinando nenhum caractere (como em JavaScript ou qualquer mecanismo não POSIX) porque as seqüências de escape regex não são suportadas dentro de expressões de colchetes. [\s\S] é analisado como expressões de colchetes que correspondem a um único caractere, \ ou s ou S


Answer #9

Em ruby ruby você pode usar a opção ' m ' (multiline):

/YOUR_REGEXP/m

Veja a documentação do Regexp em ruby-doc.org para mais informações.


Answer #10

nós também podemos usar

(.*?\n)*?

para combinar tudo, incluindo newline sem ganancioso

Isso fará com que a nova linha seja opcional

(.*?|\n)*?

Answer #11

Eu tive o mesmo problema e resolvi provavelmente não da melhor maneira, mas funciona. Eu substituí todas as quebras de linha antes de fazer minha correspondência real:

mystring= Regex.Replace(mystring, "\r\n", "")

Eu estou manipulando o HTML para que as quebras de linha não sejam realmente importantes para mim neste caso.

Tentei todas as sugestões acima sem sorte, estou usando .Net 3.5 FYI


Answer #12

Eu queria combinar um determinado bloco se em java

   ...
   ...
   if(isTrue){
       doAction();

   }
...
...
}

Se eu usar o regExp

if \(isTrue(.|\n)*}

incluiu a chave de fechamento para o bloco de método, então eu usei

if \(!isTrue([^}.]|\n)*}

para excluir a chave de fechamento da correspondência de curinga.


Answer #13

geralmente. não corresponde a novas linhas, então tente ((.|\n)*)<foobar>



Answer #15

([\s\S]*)<FooBar>

O ponto corresponde a todos, exceto as novas linhas (\ r \ n). Portanto, use \ s \ S, que corresponderá a TODOS os caracteres.


Answer #16

Em Javascript, você pode usar [^] * para procurar zero a infinitos caracteres, incluindo quebras de linha.

$("#find_and_replace").click(function() {
  var text = $("#textarea").val();
  search_term = new RegExp("[^]*<Foobar>", "gi");;
  replace_term = "Replacement term";
  var new_text = text.replace(search_term, replace_term);
  $("#textarea").val(new_text);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="find_and_replace">Find and replace</button>
<br>
<textarea ID="textarea">abcde
fghij&lt;Foobar&gt;</textarea>


Answer #17

Na expressão regular baseada em java, você pode usar [\s\S]





multiline