web-dev-qa-db-fra.com

Regex pour conserver les 4 derniers caractères d'une chaîne de longueur inconnue en utilisant C #

Je dois utiliser une expression régulière pour conserver les 4 derniers caractères d'une chaîne. Je ne connais pas la longueur de la chaîne, je dois donc commencer par la fin et compter à rebours. Le programme est écrit en c #.

Voici deux exemples de chaînes:

  • 840057
  • 1002945

J'ai besoin que le résultat soit (4 derniers caractères):

  • 0057
  • 2945

Ma ligne de code originale utilisait Regex.Replace mais je n’ai pas trouvé de regex au travail comme vous pouvez le voir dans les commentaires ci-dessous.

replacementVal = Regex.Replace(replacementVal, wildcard.Regex, wildcard.RegexReplaceBy);

J'ai changé mon code pour utiliser Regex.Match et ensuite le regex (?s)[0-9]{4}$ fonctionnait parfaitement (voir ci-dessous):

replacementVal = Regex.Replace(replacementVal, wildcard.Regex, wildcard.RegexReplaceBy);

Cependant, l'utilisation de Regex.Match rompt d'autres expressions régulières que j'utilise, par exemple, j'utilise ^(.).* pour extraire la première lettre d'un nom. Cela fonctionne lorsque vous utilisez Regex.Replace, mais échoue lorsque vous utilisez Regex.Match.

Mon code est ci-dessous, notez la ligne d'origine contenant Regex.Replace est commentée. 

Pourquoi Regex.Match fonctionne-t-il avec une expression et Regex.Replace avec une autre?

      /// Replaces a wildcard in a string
        /// </summary>
        /// <param name="str">The string for which to replace the wildcards</param>
        /// <param name="row">The DataRow in which the string exists</param>
        /// <param name="wildcard">The wildcard to replace</param>
        /// <returns>The string with the wildcard replaced</returns>
        private static string ReplaceWildcardInString(string str, DataRow row, Wildcard wildcard)
        {
            // If the string is null or empty, return it as is
            if (string.IsNullOrEmpty(str))
                return str;

            // This will hold the replacement value
            var replacementVal = string.Empty;

            // If the replacement column value is not empty
            if (!row.IsDBNullOrNull(wildcard.ReplaceByColumnName))
            {
                // Convert its value to string
                replacementVal = row[wildcard.ReplaceByColumnName].ToString();

                // Apply wildcard regex if given
                if (!string.IsNullOrEmpty(wildcard.Regex) && wildcard.RegexReplaceBy != null)
                    //replacementVal = Regex.Replace(replacementVal, wildcard.Regex, wildcard.RegexReplaceBy);
                    replacementVal = Regex.Match(replacementVal, wildcard.Regex).Value;
            }

            // Replace all wildcards with the replacement value (case insensitive)
            var wildcardPattern = Regex.Escape(string.Format("%{0}%", wildcard.Name));
            str = Regex.Replace(str, wildcardPattern, replacementVal, RegexOptions.Singleline | RegexOptions.IgnoreCase);

            // Return the new string
            return str;
        }

Merci beaucoup, j'apprécie l'aide.

14
user1226884

La méthode Regex.Replace remplace toutes les sous-chaînes ne se chevauchant pas qui correspondent à un modèle d'expression régulière avec un remplacement spécifié. 

La méthode Regex.Match recherche dans la chaîne d'entrée spécifiée la première occurrence de l'expression régulière.

Ainsi, lorsque vous avez une chaîne comme 1002945 et que vous voulez obtenir exactement 4 chiffres à partir de la fin, vous pouvez utiliser

var result = Regex.Replace("1002945", @".*([0-9]{4})$", "$1", RegexOptions.Singleline);

ou

var matchResult = Regex.Match("1002945", @"[0-9]{4}$");
if (matchResult.Success) 
{
    Console.WriteLine(matchResult.Value);
}

Lorsque vous remplacez, vous devez faire correspondre toute la chaîne, ne faites correspondre et capture que les quatre derniers caractères qui sont des chiffres et affirmez que l'index des expressions rationnelles se trouve à la fin de la chaîne ($). Notez que l'utilisation de l'option RegexOptions.Singleline permet à . de correspondre au caractère newline, auquel il ne correspond pas par défaut. La chaîne de remplacement doit être $1, la référence de remplacement du premier groupe de capture qui capture les chiffres.

Lorsque vous utilisez Regex.Match("1002945", @"[0-9]{4}$").Value, vous faites correspondre les 4 chiffres suivis de la fin de la chaîne ou d’une nouvelle ligne et de la fin de la chaîne (c’est parce que $ correspond de cette manière, si vous ne souhaitez pas autoriser une correspondance avant une chaîne). retour à la ligne et fin de chaîne, utilisez \z manchor). Lorsque la correspondance est obtenue, vous pouvez vérifier le succès ou l'échec à l'aide de matchResult.Success et, le cas échéant, obtenir le matchResult.Value. Vous n'avez plus besoin de RegexOptions.Singleline puisqu'il n'y a pas de . dans l'expression régulière.

12
Wiktor Stribiżew
.*(?=.{4})$

correspondra aux quatre derniers caractères de la chaîne. Si vous remplacez cette correspondance par String.Empty, il ne reste que ces quatre caractères.

Si la chaîne contient moins de quatre caractères, ils resteront dans la chaîne car l'expression régulière ne correspondra pas du tout, il n'y a donc rien à remplacer.

8
Tim Pietzcker

Vous n'avez pas besoin d'utiliser regex à cette fin.

string MyLast4Characters = MyString.Substring(((MyString.Length >= 4) ? (MyString.Length - 4) : (0)));

Cette partie ((MyString.Length >= 4) ? (4) : (0)) est faite pour vérifier si la chaîne d'origine est plus longue ou égale à 4 caractères, elle retournera ensuite les 4 derniers caractères, sinon la chaîne entière

3
Cid

Si cela doit être regex, je pense que vous voulez: .{4}(?=\s|$)

Mais je conviens que les expressions rationnelles ne sont probablement pas la meilleure solution ici.

Une dépression:

. : any character {4} : exacty four times (?= : followed by \s : white space | : or $ : a line ending ) : end the followed by section

1
Ian Martin

Je voudrais utiliser la méthode Regex.Match.
Il ne correspond qu'à ce dont vous avez besoin. 

Vous pouvez l'utiliser de deux manières. 

string str = "asdf 12345";
if (str.Length > 4)
{
    // Abbreviated ..
    Console.WriteLine( "{0}", Regex.Match(str, @"(?s).{5}$").Value );

    // Verbose ...
    Regex rx = new Regex(@"(?s).{5}$");
    str = rx.Match(str).Value;
    Console.WriteLine( "{0}", str );
}
else {} // Do something else

Sortie 

12345
12345
0
sln

vous pouvez essayer d'utiliser Reverse() à cette fin 

Par exemple:- 

string input = "1002945";
string rev = new string(input.Reverse().ToArray());
string res = null;

Match match = Regex.Match(rev, @"\d{4}");
if (match != null && !String.IsNullOrEmpty(match.Value))
{
   res = new string(match.Value.Reverse().ToArray());
}

sortie:- 

2945

échantillon Dot.fiddle

0
Lucifer

J'utiliserais Regex.Match autant que possible avec les groupes correspondants:

string str = "Hello :) 1002945";
string pattern = @"(.).*(\d{4})$";
Match match = Regex.Match(str, pattern);
if (match.Success)
{
    string firstChar = match.Groups[1].Value;
    string lastNumber = match.Groups[2].Value;
    Console.WriteLine("First character : " + firstChar);
    Console.WriteLine("Last number : " + lastNumber);
}

Sortie:

First character : H
Last number : 2945
0
teikitel

Je suppose que ceci est quelque chose avec votre RegexOptions. Dans mon exemple, j'utilise le mode SingleLine ((?s)) et la chaîne multiligne:

static void RegexTest()
{
    string str = "i am long string\r\nwith the number 1002945";
    string pattern = @"(?s)[0-9]{4}$"; // or @"(?s).{4}$"
    string num = Regex.Match(str, pattern).Value;
}
0
JohnyL