Expresiones de límite de palabras Regex

Digamos por ejemplo que tengo la siguiente cadena "one two(three) (three) four five" y quiero reemplazar "(three)" por "(four)" pero no dentro de las palabras. ¿Cómo lo haría?

Básicamente, quiero hacer una regex replace y terminar con la siguiente cadena:

 "one two(three) (four) four five" 

He intentado la siguiente expresión regular pero no funciona:

 @"\b\(three\)\b" 

Básicamente, estoy escribiendo un código de búsqueda y reemplazo, y le doy al usuario las opciones habituales para que coincida con el caso, coincida con la palabra completa, etc. En este caso, el usuario eligió hacer coincidir palabras completas, pero no sé qué texto buscará ser.

Tu problema proviene de una mala comprensión de lo que realmente significa. Es cierto que no es obvio.

La razón por la cual \b\(three\)\b no coincide con los tres en su cadena de entrada es la siguiente:

  • \b significa: el límite entre un carácter de palabra y un carácter de no palabra .
  • Las letras (por ejemplo, az) se consideran caracteres de palabras .
  • Los signos de puntuación como ( se consideran caracteres que no son palabras .

Aquí está su cadena de entrada de nuevo, estirada un poco, y he marcado los lugares donde \b coincide:

  onetwo ( three ) ( three ) fourfive ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ 

Como puede ver aquí, hay un \b entre “dos” y “(tres)”, pero no antes del segundo “(tres)”.

La moraleja de la historia? La “búsqueda de palabras completas” no tiene mucho sentido si lo que estás buscando no es solo una palabra (una cadena de letras). Como tiene caracteres de puntuación (paréntesis) en su cadena de búsqueda, no es como tal una “palabra”. Si buscó una palabra que consta únicamente de caracteres de palabra , entonces \b haría lo que esperaba.

Por supuesto, puede usar una Regex diferente para hacer coincidir la cadena solo si está rodeada de espacios u ocurre al principio o al final de la cadena:

 (^|\s)\(three\)(\s|$) 

Sin embargo, el problema con esto es, por supuesto, que si busca “tres” (sin los paréntesis), no encontrará el que está en “(tres)” porque no tiene espacios a su alrededor, aunque en realidad es una palabra completa.

Creo que la mayoría de los editores de texto (incluido Visual Studio) usarán \b solo si la cadena de búsqueda realmente comienza y / o termina con un carácter de palabra:

 var pattern = Regex.Escape(searchString); if (Regex.IsMatch(searchString, @"^\w")) pattern = @"\b" + pattern; if (Regex.IsMatch(searchString, @"\w$")) pattern = pattern + @"\b"; 

De esta forma, encontrarán “(tres)” incluso si selecciona “palabras completas solamente”.

Aquí un código simple que puede interesarle:

  string pattern = @"\b" + find + @"\b"; Regex.Replace(stringToSearch, pattern, replace, RegexOptions.IgnoreCase); 

Código fuente: snip2code – C #: reemplaza una palabra exacta en una oración

Recientemente me encontré con un problema similar en javascript tratando de hacer coincidir los términos con un carácter ‘$’ principal solo como palabras separadas, por ejemplo, si $ hot = ‘FUZZ’, entonces:

 "some $hot $hotel bird$hot pellets" ---> "some FUZZ $hotel bird$hot pellets" 

La expresión regular /\b\$hot\b/g (mi primera suposición) no funcionó por la misma razón por la que los parens no coincidían en la pregunta original: como caracteres que no son palabras, no hay límite de palabra o palabra que los precede con espacios en blanco o un inicio de cadena.

Sin embargo, la expresión regular /\B\$hot\b/g coincide, lo que muestra que las posiciones no marcadas en el excelente ejemplo de @ timwi coinciden con el término \ B. Esto no fue intuitivo para mí porque ") (" no está hecho de caracteres de palabras regulares. Pero supongo que dado que \ B es una inversión de la clase \ b, no tiene que ser caracteres de palabras, simplemente no tiene que ser – no- personajes de palabras 🙂

Como dijo Gopi, pero (teóricamente) atrapa solo (three) no two(three) :

 string input = "one two(three) (three) four five"; string output = input.Replace(" (three) ", " (four) "); 

Cuando pruebo eso, obtengo: "one two(three) (four) four five" Solo recuerde que el espacio en blanco también es un carácter de cadena, por lo que también puede ser reemplazado. Si hiciera esto:

 //use same input string output = input.Replace(" ", ";"); 

Me gustaría obtener one;two(three);(three);four;five"