2010-08-12 21 views
24

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

Básicamente quiero hacer una expresión regular reemplazar y termina con la siguiente cadena:

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

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

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

Básicamente soy escribir 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 esta instancia, el usuario ha elegido hacer coincidir palabras completas, pero no sé cuál será el texto que se busca.

+0

Cualquier cosa cada lado de una (o) será automáticamente un límite de la palabra, porque no es entre dos caracteres de palabra – Gareth

Respuesta

48

Su problema se deriva de una mala interpretación de lo que significa en realidad \b. Es cierto que no es obvio.

La razón \b\(three\)\b no coincide con los tríos en su cadena de entrada es la siguiente:

  • \b significa: el límite entre un personaje palabra y un carácter no-palabra.
  • Las letras (por ejemplo, a-z) se consideran caracteres de palabra.
  • Los signos de puntuación como ( se consideran caracteres sin palabra.

Aquí es su cadena de entrada de nuevo, estiró un poco, y he marcado los lugares donde \b partidos

o n e t w o (t h r e e) (t h r e e) f o u r f i v e 
↑  ↑ ↑  ↑ ↑   ↑  ↑   ↑ ↑  ↑ ↑  ↑ 

Como se 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.

Usted puede, por supuesto, utilizar una expresión regular para emparejar la cadena sólo si rodeado de espacios o se produce al principio o al final de la cadena:

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

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

creo que la mayoría de los editores de texto (incluyendo Visual Studio) usarán \b sólo si la cadena de búsqueda en realidad 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 esa manera se van a encontrar “(tres)” incluso si selecciona "palabras completas solamente".

+0

Posiblemente no tiene sentido pero así es como Me gustaría que funcione. ¿Tienes alguna idea de cómo podría hacer esto? Básicamente me gustaría imitar la funcionalidad de buscar y reemplazar dentro de Visual Studio. – CroweMan

+0

@CroweMan: Te estás contradiciendo a ti mismo. Usted dijo: "No quiero" que se reemplacen dos (tres) ", pero Visual Studio sí. – Timwi

+0

Muchas gracias. ¡Eres una estrella! – CroweMan

-1

Como dijo Gopi, pero (en teoría) la captura única (three) no two(three):

string input = "one two(three) (three) four five"; 

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

Cuando la prueba de que, me sale: "one two(three) (four) four five" Sólo recuerde que un espacio en blanco es una cadena de caracteres, también, para que pueda también ser reemplazado. Si lo hice:

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

que tendría one;two(three);(three);four;five"

+0

el problema es que el usuario está introduciendo el texto en un cuadro de búsqueda y reemplazo, y han seleccionado "emparejar palabras completas". Así que necesito usar algo inteligente como expresiones regulares y no puedo simplemente agregar un "" antes o después de la expresión ya que el carácter que procesa podría ser un ',' u otra cosa – CroweMan

0

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, p. Ej. Si $ calientes = '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 los parens no ha producido en la pregunta original - como caracteres que no sean palabras, no hay límite de palabra/sin palabra que los precede con espacios en blanco o un inicio de cadena.

Sin embargo la expresión regular /\B\$hot\b/ghace partido, lo que demuestra que las posiciones no marcados en excelente ejemplo de @ Timwi coinciden con el término \ B. Esto no fue intuitivo para mí porque ") (" no está hecho de caracteres de palabras regex. Pero supongo que como \ B es una inversión de la clase \ b, no tiene que ser caracteres de palabra, solo tiene que ser caracteres de palabra no :) :)

Cuestiones relacionadas