Czy istnieje jakaś funkcja, aby zapytać oczekiwane wejścia i formaty z ciągiem formatu - I.E. One przeznaczony jako pierwszy argument funkcji String.Format?

Na przykład dany:

"On {0:yyyyy-MM-dd} do {1} and earn {2:C2}"

Chciałbym wrócić coś takiego:

{"yyyyy-MM-dd", null, "C2"}

Myślę, że REGEX jest jedną możliwością, ale jest coś wstępnego, że haczyki do tej samej logiki, co String.Format?

c#
0
geoff_h 16 luty 2017, 14:28

2 odpowiedzi

Najlepsza odpowiedź

String.format sam nie przeanalizuje ciąg formatu. Kończy się wywołując wewnętrzną stringbuilder.appendformathelper Metoda, która Traktuje sznurki formatu tylko jako łańcuchy rozliczane. Nie próbuje ich analizować. Format jest przekazywany bezpośrednio do metody formatury typu argumentu. Wydajność formatowania łańcucha jest krytyczna, zarówno dla środowiska wykonawczego, jak i aplikacji.

Możesz użyć wyrażenia regularnego, aby analizować ciąg formatu. Musisz zadbać o ucieczkowe szelki ({{, {}) i łańcuchy wyrównania.

Regex {(?<index>\d+)(,(?<algn>-?\d+?))?(:(?<fmt>.*?))?} Wyodrębnia segmenty indeksu, wyrównania i formatów jako nazwanych grup. Nie dba o uciekające się szelki * wyraźnie. Uniknie {{ {}, ale nie {{2,20:N{}:

var regex=new System.Text.RegularExpressions.Regex(@"{(?<index>\d+)(,(?<algn>-?\d+?))?(:(?<fmt>.*?))?}");
var matches=regex.Matches("asdf{0:d2} {1:yyyy-MM-dd} {2,-20:N2}");
foreach(Match match in matches)
{
    Console.WriteLine("{0,-5} {1,-15} {2,-15}",
                       match.Groups["index"].Value, 
                       match.Groups["algn"].Value,
                       match.Groups["fmt"].Value);
}

Powróci:

0                d2             
1                yyyy-MM-dd     
2     -20        N2             

Składnia (?<name>...) przechwytuje wzór i ujawnia go jako nazwaną grupę. (?<index>\d+) przechwytuje sekwencję cyfr i ujawnia go jako grupa index.

? w .*? Określa nieczelny mecz. Zazwyczaj regex jest chciwy - będzie przechwytywać jak najwięcej znaków, jak to możliwe. Korzystając z .*? REGEX przechwytuje jako kilka znaków, jak to możliwe przed rozpoczęciem następnego wzoru. Dlatego grupa opcjonalna algn zatrzymuje się w :.

1
Panagiotis Kanavos 16 luty 2017, 12:33

Szanse nie są dla tego standardu. Użyj Regex, łatwo:

var args = new List<string>();
var str = "On {0:yyyyy-MM-dd} do {1} and earn {2:C2}";
MatchCollection matches = Regex.Matches(str, @"\{\d+[^\{\}]*\}");
foreach (Match match in matches)
{
  string obj = null;
  var split = match.ToString().Split(':');
  if (split.Length == 2) obj = split.Last().Trim(' ', '}', '{');
  args.Add(obj);
}

// Result: args = {"yyyyy-MM-dd", null, "C2"}
0
Ivan Kishchenko 16 luty 2017, 11:53