Класс генерации строк на C#
Класс позволяет генерировать строку в соответствии с определенным форматом, заданным в стиле регулярных выражений.
Например, так выглядит генерация GUID:
Также есть поддержка любых вставок между группами:
При использовании символов ‘$’, ‘[', ']‘, ‘*’, ‘-‘, не забывайте их экранировать следующим образом:
var s = "\\$\\[a\\-b\\]"; или var s = @"\$\[a\-b\]";
В качестве примера использования можете взглянуть на простейший генератор паролей, который выглядит следующим образом:
Исходный код класса:
Код может быть кривоват, но со всеми генерируемыми мною строками справлялся.
Например, так выглядит генерация GUID:
var g = new StringGenerator(@"{$[:xdigit:]*8-$[:xdigit:]*4-$[:xdigit:]*4-$[:xdigit:]*4-$[:xdigit:]*12}");
MessageBox.Show(g.Process()); // {9caea44a-01fc-a2a7-6b99-3f7fba5a0aef}
Также есть поддержка любых вставок между группами:
var g = new StringGenerator(@"Username: $[\w]*5; Password: $[\w]*8");
MessageBox.Show(g.Process()); // Username: NBFxQ; Password: H8xA74g6
При использовании символов ‘$’, ‘[', ']‘, ‘*’, ‘-‘, не забывайте их экранировать следующим образом:
var s = "\\$\\[a\\-b\\]"; или var s = @"\$\[a\-b\]";
В качестве примера использования можете взглянуть на простейший генератор паролей, который выглядит следующим образом:
Исходный код класса:
using System;
using System.Collections.Generic;
using System.Linq;
class StringGenerator
{
private readonly Dictionary<string, string> _replaces = new Dictionary<string, string>
{
{":digit:", @"0-9"},
{"\\d", @"0-9"},
{":alnum:", @"0-9A-Za-z"},
{"\\w", @"0-9A-Za-z"},
{":alpha:", @"A-Za-z"},
{":blank:", @" "},
{"\\W", @" "},
{":xdigit:", @"0-9a-f"},
{":punct:", @".,""'?!;:#\$%&()*+-/<>=@\[\]\\^_{}|~"},
{":upper:", @"A-Z"},
{":lower:", @"a-z"}
};
private string _pattern;
private readonly Random _random = new Random(Environment.TickCount);
public StringGenerator(string pattern)
{
if (
(pattern.Split('[').Length - pattern.Split(new[] { @"\[" }, StringSplitOptions.None).Length != pattern.Split(']').Length - pattern.Split(new[] { @"\]" }, StringSplitOptions.None).Length)
||
(pattern.Split('[').Length - pattern.Split(new[] { @"\[" }, StringSplitOptions.None).Length != pattern.Split('$').Length - pattern.Split(new[] { @"\$" }, StringSplitOptions.None).Length)
)
{
throw new ArgumentException("Number of non escaped characters '[', ']' and '$' must be the same.");
}
_pattern = pattern;
PreparePattern();
}
private string PreparePattern()
{
for (var i = 0; i < _pattern.Length; i++)
{
char currentChar = _pattern[i];
char prevChar = (i == 0) ? '\0' : _pattern[i - 1];
char nextChar = (_pattern.Length - 1 == i) ? '\0' : _pattern[i + 1];
if (currentChar == '*' && prevChar != '\\')
{
var scan = i + 1;
var countString = "";
while (_pattern.Length != scan && char.IsDigit(_pattern[scan]))
{
countString += _pattern[scan];
scan++;
}
if (countString == string.Empty)
{
throw new ArgumentException("Invalid number after unescaped '*'");
}
int count = Convert.ToInt32(countString);
var group = _pattern.Substring(0, i);
group = group.Substring(group.LastIndexOf("$["));
string replacement = "";
for (int r = 0; r < count; r++)
{
replacement += group;
}
_pattern = _pattern.Replace(group + "*" + count, replacement);
return PreparePattern();
}
}
return _pattern;
}
public string Process()
{
string output = "";
for (var i = 0; i < _pattern.Length; i++)
{
char currentChar = _pattern[i];
char prevChar = (i == 0) ? '\0' : _pattern[i - 1];
char nextChar = (_pattern.Length - 1 == i) ? '\0' : _pattern[i + 1];
if (currentChar == '\\' && (nextChar == '$' || nextChar == '[' || nextChar == ']'))
{
output += nextChar;
i++;
continue;
}
if (currentChar == '$')
{
if (nextChar != '[')
{
throw new ArgumentException("Invalid format, no '[' after '$' at position " + i);
}
var atBrackets = _pattern.Substring(i, _pattern.IndexOf(']', i) - i).Substring("$[".Length);
output += ProcessBracket(atBrackets);
i += ("[" + atBrackets + "]").Length;
continue;
}
output += currentChar;
}
return output;
}
private char ProcessBracket(string bracketInner)
{
if (string.Empty == bracketInner) return '\0';
bracketInner = _replaces.Aggregate(bracketInner, (current, replacement) => current.Replace(replacement.Key, replacement.Value));
var validChars = new List<int>();
for (var i = 0; i < bracketInner.Length; i++)
{
char currentChar = bracketInner[i];
char prevChar = (i == 0) ? '\0' : bracketInner[i - 1];
char nextChar = (bracketInner.Length - 1 == i) ? '\0' : bracketInner[i + 1];
if (currentChar == '\\')
{
validChars.Add(nextChar);
i++;
continue;
}
if (currentChar == '-')
{
Enumerable.Range(prevChar, nextChar - prevChar + 1).ToList().ForEach(validChars.Add);
i++;
continue;
}
validChars.Add(currentChar);
}
return (char)validChars[_random.Next(0, validChars.Count)];
}
}
Код может быть кривоват, но со всеми генерируемыми мною строками справлялся.
Скачать:
10.02.2015, 10:03 -
Категория: Статьи » Программирование » C#