regular - regex c# ejemplos
¿Necesita realizar una búsqueda con comodines(*,?, Etc.) en una cadena usando Regex (10)
Necesito realizar una búsqueda con comodines ( *
, ?
, Etc.) en una cadena. Esto es lo que he hecho:
string input = "Message";
string pattern = "d*";
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
if (regex.IsMatch(input))
{
MessageBox.Show("Found");
}
else
{
MessageBox.Show("Not Found");
}
Con el código anterior, el bloque "Encontrado" está pegando pero en realidad ¡no debería!
Si mi patrón es "e *", solo debe "Buscarse".
Mi comprensión o requisito es d * search, debería encontrar el texto que contiene "d" seguido de cualquier carácter.
¿Debo cambiar mi patrón como "d. *" Y "e. *"? ¿Hay algún soporte en .NET para Wild Card que internamente lo hace mientras usa la clase Regex?
Creo que @Dmitri tiene una buena solución en Matching Strings con wildcard https://.com/a/30300521/1726296
Basado en su solución, he creado dos métodos de extensión. (el crédito va para él)
Puede ser útil.
public static String WildCardToRegular(this String value)
{
return "^" + Regex.Escape(value).Replace("//?", ".").Replace("//*", ".*") + "$";
}
public static bool WildCardMatch(this String value,string pattern,bool ignoreCase = true)
{
if (ignoreCase)
return Regex.IsMatch(value, WildCardToRegular(pattern), RegexOptions.IgnoreCase);
return Regex.IsMatch(value, WildCardToRegular(pattern));
}
Uso:
string pattern = "file.*";
var isMatched = "file.doc".WildCardMatch(pattern)
o
string xlsxFile = "file.xlsx"
var isMatched = xlsxFile.WildCardMatch(pattern)
De http://www.codeproject.com/KB/recipes/wildcardtoregex.aspx :
public static string WildcardToRegex(string pattern)
{
return "^" + Regex.Escape(pattern)
.Replace(@"/*", ".*")
.Replace(@"/?", ".")
+ "$";
}
Entonces algo como foo*.xls?
se transformará en ^foo.*/.xls.$
.
Debe escapar símbolos Regex especiales en el patrón de entrada de caracteres comodín (por ejemplo, el patrón *.txt
será equivalente a ^.*/.txt$
). Por lo tanto, las barras, los tirantes y muchos símbolos especiales deben reemplazarse con @"/" + s
, donde s
- símbolo Regex especial
Es posible que desee utilizar WildcardPattern
del ensamblado System.Management.Automation
. Vea mi respuesta here .
La formulación de expresión regular correcta de la expresión glob d*
es ^d
, lo que significa que coincide con cualquier cosa que comience con d
.
string input = "Message";
string pattern = @"^d";
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);
(El @coting no es necesario en este caso, pero es una buena práctica, ya que muchas expresiones regulares usan escapes de barra invertida que deben dejarse en blanco, y también indica al lector que esta cadena es especial).
Necesita convertir su expresión de comodín en una expresión regular. Por ejemplo:
private bool WildcardMatch(String s, String wildcard, bool case_sensitive)
{
// Replace the * with an .* and the ? with a dot. Put ^ at the
// beginning and a $ at the end
String pattern = "^" + Regex.Escape(wildcard).Replace(@"/*", ".*").Replace(@"/?", ".") + "$";
// Now, run the Regex as you already know
Regex regex;
if(case_sensitive)
regex = new Regex(pattern);
else
regex = new Regex(pattern, RegexOptions.IgnoreCase);
return(regex.IsMatch(s));
}
Puede hacer un comodín simple sin RegEx utilizando una función de Visual Basic llamada LikeString.
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
if (Operators.LikeString("This is just a test", "*just*", CompareMethod.Text))
{
Console.WriteLine("This matched!");
}
Si usa CompareMethod.Text
, comparará las mayúsculas y minúsculas. Para la comparación de mayúsculas y minúsculas, puede usar CompareMethod.Binary
.
Más información aquí: http://www.henrikbrinch.dk/Blog/2012/02/14/Wildcard-matching-in-C
Todo el código superior no es correcto hasta el final.
Esto se debe a que al buscar zz * foo * o zz * no obtendrá los resultados correctos.
Y si busca "abcd *" en "abcd" en TotalCommander, encontrará un archivo abcd para que todo el código superior sea incorrecto.
Aquí está el código correcto.
public string WildcardToRegex(string pattern)
{
string result= Regex.Escape(pattern).
Replace(@"/*", ".+?").
Replace(@"/?", ".");
if (result.EndsWith(".+?"))
{
result = result.Remove(result.Length - 3, 3);
result += ".*";
}
return result;
}
Windows y * nux tratan los comodines de forma diferente. *
?
y .
son procesados de una manera muy compleja por Windows, su presencia o posición cambiaría el significado de otro. Mientras que * nux lo mantiene simple, todo lo que hace es solo una coincidencia de patrón simple. Además de eso, ?
coincide Windows ?
para 0 o 1 caracteres, Linux lo compara exactamente con 1 caracteres.
No encontré documentos autorizados sobre este tema, aquí está mi conclusión basada en los días de pruebas en Windows 8 / XP (línea de comando, el comando dir
es específico, y el método Directory.GetFiles
usa las mismas reglas también) y Ubuntu Servidor 12.04.1 (comando ls
). Hice funcionar decenas de casos comunes y poco comunes, aunque también hay muchos casos fallidos.
La respuesta actual de Gabe, funciona como * nux. Si también desea un estilo de Windows, y está dispuesto a aceptar la imperfección, aquí está:
/// <summary>
/// <para>Tests if a file name matches the given wildcard pattern, uses the same rule as shell commands.</para>
/// </summary>
/// <param name="fileName">The file name to test, without folder.</param>
/// <param name="pattern">A wildcard pattern which can use char * to match any amount of characters; or char ? to match one character.</param>
/// <param name="unixStyle">If true, use the *nix style wildcard rules; otherwise use windows style rules.</param>
/// <returns>true if the file name matches the pattern, false otherwise.</returns>
public static bool MatchesWildcard(this string fileName, string pattern, bool unixStyle)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
if (pattern == null)
throw new ArgumentNullException("pattern");
if (unixStyle)
return WildcardMatchesUnixStyle(pattern, fileName);
return WildcardMatchesWindowsStyle(fileName, pattern);
}
private static bool WildcardMatchesWindowsStyle(string fileName, string pattern)
{
var dotdot = pattern.IndexOf("..", StringComparison.Ordinal);
if (dotdot >= 0)
{
for (var i = dotdot; i < pattern.Length; i++)
if (pattern[i] != ''.'')
return false;
}
var normalized = Regex.Replace(pattern, @"/.+$", "");
var endsWithDot = normalized.Length != pattern.Length;
var endWeight = 0;
if (endsWithDot)
{
var lastNonWildcard = normalized.Length - 1;
for (; lastNonWildcard >= 0; lastNonWildcard--)
{
var c = normalized[lastNonWildcard];
if (c == ''*'')
endWeight += short.MaxValue;
else if (c == ''?'')
endWeight += 1;
else
break;
}
if (endWeight > 0)
normalized = normalized.Substring(0, lastNonWildcard + 1);
}
var endsWithWildcardDot = endWeight > 0;
var endsWithDotWildcardDot = endsWithWildcardDot && normalized.EndsWith(".");
if (endsWithDotWildcardDot)
normalized = normalized.Substring(0, normalized.Length - 1);
normalized = Regex.Replace(normalized, @"(?!^)(/./*)+$", @".*");
var escaped = Regex.Escape(normalized);
string head, tail;
if (endsWithDotWildcardDot)
{
head = "^" + escaped;
tail = @"(/.[^.]{0," + endWeight + "})?$";
}
else if (endsWithWildcardDot)
{
head = "^" + escaped;
tail = "[^.]{0," + endWeight + "}$";
}
else
{
head = "^" + escaped;
tail = "$";
}
if (head.EndsWith(@"/./*") && head.Length > 5)
{
head = head.Substring(0, head.Length - 4);
tail = @"(/..*)?" + tail;
}
var regex = head.Replace(@"/*", ".*").Replace(@"/?", "[^.]?") + tail;
return Regex.IsMatch(fileName, regex, RegexOptions.IgnoreCase);
}
private static bool WildcardMatchesUnixStyle(string pattern, string text)
{
var regex = "^" + Regex.Escape(pattern)
.Replace("//*", ".*")
.Replace("//?", ".")
+ "$";
return Regex.IsMatch(text, regex);
}
Hay algo curioso, incluso la API de Windows PathMatchSpec no está de acuerdo con FindFirstFile . Solo prueba a1*.
, FindFirstFile
dice que coincide con a1
, PathMatchSpec
dice que no.
d*
significa que debe coincidir con cero o más caracteres " d
". Entonces cualquier cadena es una coincidencia válida. Prueba d+
lugar!
Para tener soporte para patrones de comodines, reemplazaría los comodines con los equivalentes de RegEx. Al igual que *
convierte en .*
Y ?
se convierte en .?
. Entonces tu expresión anterior se convierte en d.*