¿Cómo hago coincidir cualquier carácter a través de varias líneas en una expresión regular?


Por ejemplo, esta expresión regular

(.*)<FooBar>

Coincidirá:

abcde<FooBar>

Pero, ¿cómo consigo que coincida a través de múltiples líneas?

abcde
fghij<FooBar>
Author: Bobulous, 2008-10-01

20 answers

Depende del idioma, pero debe haber un modificador que pueda agregar al patrón de expresiones regulares. En PHP es:

/(.*)<FooBar>/s

El s al final hace que el punto coincida con todos los caracteres, incluidas las líneas nuevas.

 182
Author: Jeremy Ruten,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-01 18:52:18

Prueba esto:

((.|\n)*)<FooBar>

Básicamente dice "cualquier carácter o una nueva línea" repetido cero o más veces.

 242
Author: levik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-01 18:52:27

Si estás usando Eclipse search, puedes habilitar la opción "DOTALL" para hacer '.'coincide con cualquier carácter, incluidos los delimitadores de línea: simplemente agregue "(?s)" al principio de la cadena de búsqueda. Ejemplo:

(?s).*<FooBar>
 56
Author: Paulo Merson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-25 13:16:55

La pregunta es, ¿puede . el patrón coincidir con cualquier carácter? La respuesta varía de un motor a otro. La principal diferencia es si el patrón es utilizado por una biblioteca de expresiones regulares POSIX o no POSIX.

Nota especial sobre lua-patterns: no se consideran expresiones regulares, pero . coincide con cualquier carácter allí, al igual que los motores basados en POSIX.

Otra a matlab y octava: el . coincide con cualquier carácter por defecto (demo): str = "abcde\n fghij<Foobar>"; expression = '(.*)<Foobar>*'; [tokens,matches] = regexp(str,expression,'tokens','match'); (tokens contendrá un elemento abcde\n fghij.

Además, en todas las gramáticas regex de boost el punto coincide con los saltos de línea por defecto. La gramática ECMAScript de Boost te permite desactivar esto con regex_constants::no_mod_m (source ).

En cuanto a oracle (está basado en POSIX), use n opción (demo): select regexp_substr('abcde' || chr(10) ||' fghij<Foobar>', '(.*)<Foobar>', 1, 1, 'n', 1) as results from dual

Motores basados en POSIX :

Tcl (demo), postgresql (demo), r (TRE, base R motor por defecto con no perl=TRUE, para base R con perl=TRUE o para strintr/stringi patrones, utilice el modificador inline (?s)) (demo ). Un mero . ya coincide con los saltos de línea, sin necesidad de usar ningún modificador.

Motores no basados en POSIX :

  • php - Use s modificador Modificador PCRE_DOTALL: preg_match('~(.*)<Foobar>~s', $s, $m) (demo)
  • c # - Uso RegexOptions.Singleline flag ( demo):
    - var result = Regex.Match(s, @"(.*)<Foobar>", RegexOptions.Singleline).Groups[1].Value;
    - var result = Regex.Match(s, @"(?s)(.*)<Foobar>").Groups[1].Value;
  • powershell - Usar (?s) opción en línea: $s = "abcde`nfghij<FooBar>"; $s -match "(?s)(.*)<Foobar>"; $matches[1]
  • perl - Use s modificador (o (?s) versión en línea al inicio) ( demo): /(.*)<FooBar>/s
  • python - Use re.DOTALL (o re.S) banderas o (?s) modificador en línea (demo): m = re.search(r"(.*)<FooBar>", s, flags=re.S) (y luego if m:, print(m.group(1)))
  • java - Use Pattern.DOTALL modificador (o flag inline (?s) ) (demo): Pattern.compile("(.*)<FooBar>", Pattern.DOTALL)
  • groovy - Use (?s) modificador de patrón (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 [^] o soluciones alternativas [\d\D] / [\w\W] / [\s\S] (demo): s.match(/([\s\S]*)<FooBar>/)[1]
  • c++ (std::regex) Utilice [\s\S] o las soluciones JS (demo): regex rex(R"(([\s\S]*)<FooBar>)");
  • vba - Use el mismo enfoque que en JavaScript, ([\s\S]*)<Foobar>.
  • ruby - Use /m Modificador MULTILÍNEA ( demo): s[/(.*)<Foobar>/m, 1]
  • go - Usa el modificador inline (?s) al inicio (demo): re: = regexp.MustCompile(`(?s)(.*)<FooBar>`)
  • swift - Uso dotMatchesLineSeparators o (más fácil) pasar el modificador inline (?s) al patrón: let rx = "(?s)(.*)<Foobar>"
  • objective-c - Igual que Swift, (?s) funciona de la manera más fácil, pero así es como la opción se puede utilizar: NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&regexError];
  • re2, google-apps-script - Use (?s) modificador (demo): "(?s)(.*)<Foobar>" (en Hojas de cálculo de Google, =REGEXEXTRACT(A2,"(?s)(.*)<Foobar>"))

NOTAS SOBRE (?s):

En la mayoría de los motores no POSIX, (?s) el modificador en línea (o la opción de bandera incrustada) se puede usar para forzar . para que coincida con los saltos de línea.

Si se coloca al comienzo del patrón, (?s) cambia el bahavior de todos . en el patrón. Si el (?s) se coloca en algún lugar después del principio, solo se verán afectados aquellos . que se encuentren a la derecha de él a menos que este sea un patrón pasado a Python re. En Python re, independientemente de la ubicación (?s), todo el patrón . se ve afectado. El efecto (?s) se deja de usar (?-s). Un grupo modificado se puede usar para afectar solo un rango especificado de un patrón de expresiones regulares (por ejemplo, Delim1(?s:.*?)\nDelim2.* hará que el primer .*? coincida a través de nuevas líneas y el segundo .* solo coincidirá con el resto de la línea).

Nota POSIX :

En motores no regex, para que coincida con cualquier char, [\s\S] / [\d\D] / [\w\W] se pueden usar construcciones.

En POSIX, [\s\S] no coincide con ningún char (como en JavaScript o cualquier motor que no sea POSIX) porque las secuencias de escape de expresiones regulares no son compatibles dentro de las expresiones de corchete. [\s\S] se analiza como expresiones de corchete que coinciden con un solo carácter, \ o s o S.

 30
Author: Wiktor Stribiżew,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-24 20:42:55

En JavaScript, use /[\S\s]*<Foobar>/. Fuente

 29
Author: Abbas Shahzadeh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-23 01:15:00

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

El punto coincide con todos excepto con las nuevas líneas (\r\n). Así que use \s\S, que coincidirá con TODOS los caracteres.

 23
Author: samwize,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-19 17:59:45

En Ruby ruby puedes usar la opción' m ' (multilínea):

/YOUR_REGEXP/m

Ver la documentación de expresiones regulares en ruby-doc.org para más información.

 18
Author: vibaiher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-31 07:54:09

"." normalmente no coincide con los saltos de línea. La mayoría de los motores regex le permiten agregar la bandera S (también llamada DOTALL y SINGLELINE) para hacer que "." también coincida con las nuevas líneas. Si eso falla, podrías hacer algo como [\S\s].

 8
Author: Markus Jarderot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-25 21:09:27

Para Eclipse funcionó la siguiente expresión:

Foo

Jadajada Bar "

Expresión regular:

Foo[\S\s]{1,10}.*Bar*
 7
Author: Gordon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-03 11:52:40
/(.*)<FooBar>/s

La s causa el Punto (.) para que coincidan los retornos de carro

 5
Author: Bill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-01 18:54:07

También podemos usar

(.*?\n)*?

Para que coincida con todo, incluyendo nueva línea sin codicioso

Esto hará que la nueva línea opcional

(.*?|\n)*?
 5
Author: RAN_0915,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-06 07:48:29

Tenga en cuenta que (.|\n)* puede ser menos eficiente que (por ejemplo) [\s\S]* (si las expresiones regulares de su lenguaje admiten tales escapes) y que encontrar cómo especificar el modificador que hace . también coinciden con las nuevas líneas. O puedes ir con alternativas POSIXy como [[:space:][:^space:]]*.

 3
Author: tye,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-02 03:31:26

Use RegexOptions.Singleline, cambia el significado de . para incluir nuevas líneas

Regex.Reemplazar (contenido, SearchText, replaceText, RegexOptions.Singleline);

 3
Author: shmall,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-04-13 00:42:03

Solución:

Use el modificador de patrón sU obtendrá la coincidencia deseada en PHP.

Ejemplo:

preg_match('/(.*)/sU',$content,$match);

Fuente:

Http://dreamluverz.com/developers-tools/regex-match-all-including-new-line http://php.net/manual/en/reference.pcre.pattern.modifiers.php

 2
Author: Sian Lerk Lau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-04 11:00:26

En expresiones regulares basadas en java se puede usar [\s\S]

 2
Author: Kamahire,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-25 19:01:48

En el contexto del uso dentro de los lenguajes, las expresiones regulares actúan sobre cadenas, no sobre líneas. Así que debería ser capaz de utilizar la expresión regular normalmente, suponiendo que la cadena de entrada tiene varias líneas.

En este caso, la expresión regular dada coincidirá con toda la cadena, ya que "" está presente. Dependiendo de los detalles de la implementación regex, el valor $1 (obtenido de la "(.*)") será "fghij" o "abcde\nfghij". Como otros han dicho, algunas implementaciones le permiten controlar si el "."coincidirá con la nueva línea, dándote la opción.

El uso de expresiones regulares basadas en líneas es generalmente para cosas de línea de comandos como egrep.

 1
Author: nsayer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-01 18:54:46

Tuve el mismo problema y lo resolví probablemente no de la mejor manera, pero funciona. He reemplazado todos los saltos de línea antes de hacer mi partido real:

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

Estoy manipulando HTML para que los saltos de línea realmente no me importen en este caso.

Probé todas las sugerencias anteriores sin suerte, estoy usando. Net 3.5 Para su información

 1
Author: Slee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-26 14:57:08

En general . no coincide con las nuevas líneas, así que intenta ((.|\n)*)<foobar>

 0
Author: tloach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-01 18:52:56

Quería hacer coincidir un bloque if en particular en java

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

   }
...
...
}

Si uso la expresión regular

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

Incluía la abrazadera de cierre para el bloque de método, así que usé

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

Para excluir la llave de cierre de la coincidencia de comodines.

 0
Author: Spangen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-18 09:31:21

A menudo tenemos que modificar una subcadena con algunas palabras clave repartidas entre líneas que preceden a la subcadena. Considere un elemento xml:

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

Supongamos que queremos modificar el 81, a algún otro valor, digamos 40. Primero identifique .UID.21..UID., luego omita todos los caracteres incluyendo \n hasta .PercentCompleted.. El patrón de expresión regular y la especificación replace son:

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>

El subgrupo (.|\n) es probablemente el grupo que falta $3. Si lo hacemos no captura por (?:.|\n) entonces el $3 es (<PercentComplete>). Así que el patrón y replaceSpec también puede ser:

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

Y el reemplazo funciona correctamente como antes.

 0
Author: user1348737,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-26 08:49:45