2011-06-10 42 views
12

¿Cómo podría construir una expresión regular para encontrar todas las palabras que terminan en una cadena pero que no comienzan con una cadena?Regex - Encuentra todas las palabras que coinciden que no comienzan con un prefijo específico

p. Ej. Encuentra todas las palabras que terminan en 'amigo' que no comienzan con la palabra 'niña' en la siguiente frase:

"Un novio y novia ganado un amigocuando se les pide que amistad ellos "

Los artículos en negrita deben coincidir. La palabra 'novia' no debería.

+5

Para preguntas regex, es útil mencionar en qué idioma está trabajando porque puede haber diferencias en la sintaxis de expresiones regulares para la misma tarea. – mrk

Respuesta

18

De la parte superior de mi cabeza, usted podría intentar:

\b    # word boundary - matches start of word 
(?!girl)  # negative lookahead for literal 'girl' 
\w*   # zero or more letters, numbers, or underscores 
friend   # literal 'friend' 
\b    # word boundary - matches end of word 

actualización

Aquí hay otro enfoque no es evidente que debe trabajar en cualquier aplicación moderna de expresiones regulares:

Suponiendo que desea extraer un patrón que aparece en múltiples contextos, pero solo desea que coincida si aparece en un contexto específico, puede usar una alteración donde primero especifique lo que hace No quiero y luego capturar lo que haces.

Por lo tanto, la utilización de su ejemplo, para extraer todas las palabras que están o fin en friend excepto girlfriend, tendrá que utilizar:

\b    # word boundary 
(?:    # start of non-capture group 
    girlfriend  # literal (note 1) 
|    # alternation 
    (    # start of capture group #1 (note 2) 
    \w*   # zero or more word chars [a-zA-Z_] 
    friend  # literal 
)    # end of capture group #1 
)    # end of non-capture group 
\b 

Notas:

  1. Esto es lo que no que capturar.
  2. Y esto es lo que hacer que capturar.

que se puede describir como:

  • para todas las palabras
  • primer partido 'Girlfriend', y no captan (descarte)
  • entonces encontró ningún palabra que es o termina en ' amigo' y la captura se

en javascript:

const target = 'A boyfriend and girlfriend gained a friend when they asked to befriend them'; 

const pattern = /\b(?:girlfriend|(\w*friend))\b/g; 

let result = []; 
let arr; 

while((arr=pattern.exec(target)) !== null){ 
    if(arr[1]) { 
    result.push(arr[1]); 
    } 
} 

console.log(result); 

que, cuando se ejecuta, se imprimirá:

[ 'boyfriend', 'friend', 'befriend' ] 
+0

Tenga en cuenta que, si bien muchos de los sabores de las expresiones regulares no son compatibles con la mirada hacia atrás, la mayoría admite la búsqueda anticipada. La respuesta que di funcionará en JavaScript, que no es compatible con mirar hacia atrás. –

+0

Aunque no es la respuesta más rápida, ¡+1 para la explicación! Nitpick pequeño sin embargo: '\ b' es mejor llamado un" límite de palabras ". –

+0

@BartKiers, cierto, pero en este caso sirve para delimitar el inicio y el final de la palabra. –

6

Prueba esto:

/\b(?!girl)\w*friend\b/ig 
4

esto puede funcionar:

\w*(?<!girl)friend

también se podría tratar

\w*(?<!girl)friend\w* si desea que coincida con palabras como befriended o boyfriends.

no estoy seguro de si ?<! está disponible en todas las versiones de expresiones regulares, pero esta expresión trabajaban en Expersso (que creo que es .NET).

+0

Eso siempre coincidirá con "amigo" (y una cadena vacía dentro del grupo 1) –

+0

@Bart Kiers: ¿Dónde siempre coincide? No coincide con "novia" cuando pruebo en Expresso. – FrustratedWithFormsDesigner

+0

Correcto, no coincide con la palabra "amigo" con la palabra "niña" delante de él. Lo que quise decir es que en el caso de la palabra "novio", solo coincide la palabra "amigo". Esto es lo que siempre coincidirá: solo la palabra "amigo". –

4

he cambiado la respuesta de Rob Raisch a una expresión regular que encuentra las palabras que contengan una subcadena específica, pero no que también contiene una subcadena específica diferente

\b(?![\w_]*Unwanted[\w_]*)[\w_]*Desired[\w_]*\b 

Entonces, por ejemplo \ b (?! [\ W_] * mon [\ w _] *) [\ w_] * día [\ w _] * \ b encontrará cada palabra con "día" (p. Ej., Día, martes , daywalker) en ella, excepto si también contiene "mon" (por ejemplo, lunes)

Quizás sea útil para alguien.

+0

Parece que no funciona con caracteres no alfanuméricos. Por ejemplo, si quiero recuperar todos los puntos "." excepto en las palabras que comienzan con "@". (por ejemplo: Hello. @ some.thing no funciona. -> debería detectar dot después de "Hello" y al final de la oración, pero no en "@ some.thing"). – MikeL

Cuestiones relacionadas