regex - positive - ¿Cómo funciona la expresión regular ''(?<=#)[^#]+(?=#)''?
regex one (3)
Como se menciona en otro póster, se trata de regular-expressions.info/Lookarounds , construcciones especiales para cambiar lo que coincide y cuándo. Esto dice:
(?<=#) match but don''t capture, the string `#`
when followed by the next expression
[^#]+ one or more characters that are not `#`, and
(?=#) match but don''t capture, the string `#`
when preceded by the last expression
Entonces esto coincidirá con todos los personajes entre dos #
s.
Lookaheads y lookbehinds son muy útiles en muchos casos. Considere, por ejemplo, la regla "unir todas las b
s no seguidas por una a
". Tu primer intento podría ser algo así como b[^a]
, pero eso no está bien: esto también coincidirá con el bu
en bus
o el bo
en boy
, pero solo querías el b
. Y no coincidirá con el b
en la cab
, aunque eso no sea seguido por una a
, porque no hay más personajes para unir.
Para hacerlo correctamente, necesita un vistazo: b(?!a)
. Esto dice "coincide con una b
pero no coincide con una a
después, y no hagas esa parte del partido". Por lo tanto, coincidirá solo con el b
en bolo
, que es lo que quieres; también coincidirá con el b
en la cab
.
Tengo la siguiente expresión regular en un programa de C #, y tengo dificultades para entenderlo:
(?<=#)[^#]+(?=#)
Lo dividiré en lo que creo que entendí:
(?<=#) a group, matching a hash. what''s `?<=`?
[^#]+ one or more non-hashes (used to achieve non-greediness)
(?=#) another group, matching a hash. what''s the `?=`?
Entonces el problema que tengo es la parte ?<=
Y ?<
. Al leer MSDN,? ?<name>
se usa para nombrar grupos, pero en este caso el corchete angular nunca se cierra.
No pude encontrar ?=
En los documentos, y su búsqueda es realmente difícil, porque los motores de búsqueda ignorarán en su mayoría esos caracteres especiales.
Se llaman " look-arounds" : regular-expressions.info/Lookarounds
Se llaman "Miradores"; te permiten afirmar si un patrón coincide o no, sin llegar a hacer la coincidencia. Hay 4 orientaciones básicas:
- Miradas positivas: vea si PODEMOS coincidir con el
pattern
...-
(?=pattern)
- ... a la derecha de la posición actual (mirar hacia adelante ) -
(?<=pattern)
- ... a la izquierda de la posición actual (mira hacia atrás )
-
- Miradas negativas: vea si NO podemos igualar el
pattern
-
(?!pattern)
- ... a la derecha -
(?<!pattern)
- ... a la izquierda
-
Como recordatorio fácil, para un vistazo:
-
=
es positivo!
es negativo -
<
está atrás , de lo contrario es mirar hacia adelante
Referencias
Pero, ¿por qué usar lookarounds?
Se podría argumentar que las aproximaciones en el patrón anterior no son necesarias, y #([^#]+)#
hará el trabajo bien (extrayendo la cadena capturada por /1
para obtener el valor no #
).
No exactamente. La diferencia es que dado que un vistazo no coincide con el #
, se puede "usar" nuevamente en el próximo intento de encontrar una coincidencia. Simplificando hablando, las alternativas permiten que las "coincidencias" se superpongan.
Considere la siguiente cadena de entrada:
and #one# and #two# and #three#four#
Ahora, #([az]+)#
dará las siguientes coincidencias ( como se ve en rubular.com ):
and #one# and #two# and #three#four#
/___/ /___/ /_____/
Compare esto con (?<=#)[az]+(?=#)
, Que coincide con:
and #one# and #two# and #three#four#
/_/ /_/ /___/ /__/
Lamentablemente, esto no se puede demostrar en rubular.com, ya que no es compatible con lookbehind. Sin embargo, es compatible con la búsqueda anticipada, por lo que podemos hacer algo similar con #([az]+)(?=#)
, Que coincide ( como se ve en rubular.com ):
and #one# and #two# and #three#four#
/__/ /__/ /____//___/