test - regex.match c#
Expresión regular para eliminar etiquetas XML y su contenido (7)
Tengo la siguiente cadena y me gustaría eliminar <bpt *>*</bpt>
y <ept *>*</ept>
(fíjate en el contenido adicional de la etiqueta que también debe eliminarse) sin usar un analizador XML (sobrecarga demasiado grande para cuerdas diminutas).
The big <bpt i="1" x="1" type="bold"><b></bpt>black<ept i="1"></b></ept> <bpt i="2" x="2" type="ulined"><u></bpt>cat<ept i="2"></u></ept> sleeps.
Cualquier expresión regular en VB.NET o C # servirá.
¿El motor .NET regex admite negativos lookaheads? Si es así, entonces puedes usar
(<([eb])pt[^>]+>((?!<//2pt>).)+<//2pt>)
Lo que hace que The big black cat duerma. fuera de la cadena de arriba si elimina todas las coincidencias. Sin embargo, tenga en cuenta que no funcionará si ha anidado elementos bpt
/ ept
. También es posible que desee agregar /s
en algunos lugares para permitir espacios en blanco adicionales en los elementos de cierre, etc.
¿Por qué dices que la sobrecarga es demasiado grande? ¿Lo has medido? ¿O estás adivinando?
Usar un regex en lugar de un analizador apropiado es un atajo con el que puedes tropezar cuando alguien llega con algo como <bpt foo = "bar>">
Si va a utilizar una expresión regular para eliminar elementos XML, asegúrese de que su entrada XML no utilice elementos de diferentes espacios de nombres, o contenga secciones CDATA cuyo contenido no desee modificar.
La forma correcta (es decir, tanto correcta como correcta) de hacerlo es con XSLT. Una transformación XSLT que copia todo excepto un elemento específico para el resultado es una extensión trivial de la transformación de identidad. Una vez que se compila la transformación, se ejecutará de forma extremadamente rápida. Y no contendrá ningún defecto oculto.
Supongo que quieres soltar la etiqueta por completo.
(<bpt .*?>.*?</bpt>)|(<ept .*?>.*?</ept>)
Los ? después del * lo hace no codicioso, por lo que intentará hacer coincidir la menor cantidad de caracteres posible.
Un problema que tendrás es etiquetas anidadas. cosas no verían el segundo porque el primero coincide.
Si solo quieres eliminar todas las etiquetas de la cadena, usa esto (C #):
try {
yourstring = Regex.Replace(yourstring, "(<[be]pt[^>]+>.+?</[be]pt>)", "");
} catch (ArgumentException ex) {
// Syntax error in the regular expression
}
EDITAR:
Decidí agregar a mi solución una mejor opción. La opción anterior no funcionaría si hubiera etiquetas incrustadas. Esta nueva solución debería quitar todas las etiquetas <** pt *>, incrustadas o no. Además, esta solución usa una referencia retrospectiva de la coincidencia original [ser] para que se encuentre la etiqueta final coincidente exacta. Esta solución también crea un objeto Regex reutilizable para un mejor rendimiento para que cada iteración no tenga que recompilar el Regex:
bool FoundMatch = false;
try {
Regex regex = new Regex(@"<([be])pt[^>]+>.+?<//1pt>");
while(regex.IsMatch(yourstring) ) {
yourstring = regex.Replace(yourstring, "");
}
} catch (ArgumentException ex) {
// Syntax error in the regular expression
}
NOTAS ADICIONALES:
En los comentarios, un usuario expresó su preocupación de que el ''.'' patrón de coincidencia sería intensivo en la CPU. Si bien esto es cierto en el caso de un codicioso independiente ''.'', El uso del personaje no codicioso ''?'' hace que el motor de expresiones regulares solo mire hacia delante hasta que encuentre la primera coincidencia del siguiente carácter en el patrón frente a un codicioso ''.'' que requiere que el motor mire hacia adelante hasta el final de la cuerda. Uso RegexBuddy como una herramienta de desarrollo de expresiones regulares, e incluye un depurador que le permite ver el rendimiento relativo de diferentes patrones de expresiones regulares. También auto comenta tus expresiones regulares si así lo deseas, así que decidí incluir esos comentarios aquí para explicar la expresión regular utilizada anteriormente:
// <([be])pt[^>]+>.+?<//1pt>
//
// Match the character "<" literally «<»
// Match the regular expression below and capture its match into backreference number 1 «([be])»
// Match a single character present in the list "be" «[be]»
// Match the characters "pt" literally «pt»
// Match any character that is not a ">" «[^>]+»
// Between one and unlimited times, as many times as possible, giving back as needed (greedy) «+»
// Match the character ">" literally «>»
// Match any single character that is not a line break character «.+?»
// Between one and unlimited times, as few times as possible, expanding as needed (lazy) «+?»
// Match the characters "</" literally «</»
// Match the same text as most recently matched by backreference number 1 «/1»
// Match the characters "pt>" literally «pt>»
¿Hay alguna manera posible de obtener una solución global de regex.pattern para el tipo de texto xml? de esa forma me desharé de la función de reemplazo y usaré el regex. El problema es analizar si el <> viene en orden o no ... También reemplazando los caracteres reservados como ''& y así sucesivamente. Aquí está el código'' manejo especial chars functions Friend Función ReplaceSpecChars (ByVal str As String) As String Dim arrLessThan como nueva colección Dim arrGreaterThan como nueva colección If Not IsDBNull (str) Then
str = CStr(str)
If Len(str) > 0 Then
str = Replace(str, "&", "&")
str = Replace(str, "''", "'")
str = Replace(str, """", """)
arrLessThan = FindLocationOfChar("<", str)
arrGreaterThan = FindLocationOfChar(">", str)
str = ChangeGreaterLess(arrLessThan, arrGreaterThan, str)
str = Replace(str, Chr(13), "chr(13)")
str = Replace(str, Chr(10), "chr(10)")
End If
Return str
Else
Return ""
End If
Función de finalización Función de amigo ChangeGreaterLess (ByVal lh As Collection, ByVal gr As Collection, ByVal str As String) As String para i As Integer = 0 To lh.Count If CInt (lh.Item (i))> CInt (gr.Item ( i)) Entonces str = Reemplazar (str, "<", "<") ///////// problems //// End If
Next
str = Replace(str, ">", ">")
End Function Friend Function FindLocationOfChar (ByVal chr como Char, ByVal str As String) As Collection Dim arr As New Collection para i As Integer = 1 To str.Length () - 1 If str.ToCharArray (i, 1) = chr Then arr .Add (i) End If Next Return arr End Function
tiene problemas en la marca del problema
ese es un xml estándar con diferentes etiquetas que quiero analizar ...
¿Has medido esto? Me he encontrado con problemas de rendimiento usando el motor de expresiones regulares de .NET, pero por el contrario he analizado archivos xml de alrededor de 40 GB sin problemas usando el analizador Xml (sin embargo, necesitarás usar XmlReader para cadenas más grandes).
Regex
una muestra de código real y mencione sus requisitos de rendimiento: dudo que la clase Regex
sea la mejor solución aquí si el rendimiento es importante.