搜索了一下,但我只发现了用逗号大小分割的情况。这种情况不同。
为了解释我的问题,我将展示一个小例子:
JAN 01 00:00:01 <Admin> Action, May have spaces etc.
(这是一个日志条目)
我想将这个字符串解析成几个变量。第一位显然是一个日期,没有一年。在&lt;&gt;之间列出登录名,并在日志条目后面。
配置应该是这样的:
{month} {day} {hour}:{minute}:{second} <{login}> {the_rest}
这将允许更改而不需要对整个事物进行硬编码(使用拆分等)。
我认为使用正则表达式在这里可能很有用,但我对它并不是很了解,如果它在这种情况下可以使用的话。 速度并不重要,但我真的不知道如何实现这一点。
谢谢,
〜Tgys
答案 0 :(得分:3)
string line = "JAN 01 00:00:01 <Admin> Action, May have spaces etc.";
var m = Regex.Match(line, @"(\w{3} \d{2} \d{2}:\d{2}:\d{2}) \<(\w+)\>([\w ]+),([\w ]+)");
var date = DateTime.ParseExact(m.Groups[1].Value,"MMM dd HH:mm:ss",CultureInfo.InvariantCulture);
var user = m.Groups[2].Value;
var action = m.Groups[3].Value;
var text = m.Groups[4].Value;
答案 1 :(得分:1)
您可以使用拆分静止,拆分空格字符。
显然你的问题是你想在一定数量的分裂后保留空格,以便你的“其余”保持在一起。
split的可选int参数允许您提供您希望执行的最大拆分量,因此可能会提供您正在寻找的解决方法。
答案 2 :(得分:1)
您也可以将其用作正则表达式并使用捕获的组:
^(?<Month>\w{3})\s(?<Day>\d{2})\s(?<Hour>\d{2}):(?<Min>\d{2}):(?<Sec>\d{2})\s(?<User>\<(\w.+?)\>)(.+)$
编辑:错过了用户部分。
答案 3 :(得分:1)
正则表达式确实是正确的工具。首先,让我们看看如何使用硬编码的正则表达式来解析此日志。
var str = "JAN 01 00:00:01 <Admin> Action, May have spaces etc.";
var re = new Regex("^" +
@"(?<month>(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC))" +
" " +
@"(?<day>\d+)" +
" " +
@"(?<hour>\d+)" +
":" +
@"(?<the_rest>.*)" +
"$");
var match = re.Match(str);
我们在这里所做的是使用命名捕获组逐个创建正则表达式。我没有为了简洁而捕获所有相关信息,并且我没有花太多时间考虑每个组的上下文中的有效输入(例如day
将匹配999
,尽管那是不是有效的一天)。这一切都可以在以后发生;现在,see it in action。
下一步是很好地将每个捕获组的定义提取到字典中:
var groups = new Dictionary<string, string>
{
{ "month", "(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)" },
{ "day", @"\d+" },
{ "hour", @"\d+" },
{ "the_rest", ".*" },
};
鉴于此,我们现在可以使用
构建相同的正则表达式var re = new Regex("^" +
string.Format("(?<month{0}>)", groups["month"]) +
" " +
string.Format("(?<day{0}>)", groups["day"]) +
" " +
string.Format("(?<hour{0}>)", groups["hour"]) +
":" +
string.Format("(?<the_rest{0}>)", groups["the_rest"]) +
"$");
好的,这开始看起来像是可以动态构建的东西。
假设我们想要从看起来像
的规范构建它"{month} {day} {hour}:{the_rest}"
怎么做?用另一个正则表达式!具体来说,我们将使用Regex.Replace
的重载,它可以用函数的结果替换匹配:
var format = "{month} {day} {hour}:{the_rest}";
var result = Regex.Replace(format, @"\{(\w+)\}", m => groups[m.Groups[1].Value]);
回来之前
此时,我们可以传入格式规范并获取与基于此格式的输入匹配的正则表达式。还剩什么?要将正则表达式与输入匹配的结果转换回“动态”结构:
var format = "{month} {day} {hour}:{the_rest}";
var re = Regex.Replace(format,
@"\{(\w+)\}",
m => string.Format("(?<{0}>{1})", m.Groups[1].Value, groups[m.Groups[1].Value]));
var regex = new Regex("^" + re + "$", RegexOptions.ExplicitCapture);
var match = regex.Match(str);
此时:
match.Success
以查看动态构造的表达式是否与输入regex.GetGroupNames()
来获取解析中使用的组的名称match.Groups
以获得解析每个组的结果所以让我们把它们放在字典中:
var results = regex.GetGroupNames().ToDictionary(n => n, n => match.Groups[n].Value);
您现在可以创建一个方法Parse
,允许这样做:
var input = "JAN 01 00:00:01 <Admin> Action, May have spaces etc.";
var format = "{month} {day} {hour}:{the_rest}";
var results = Parse(input, format);
Parse
将识别(但不允许用户修改)"{month}"
等表达式,同时允许用户自由地混合和匹配这些表达式以解析输入。
<强> See the final result 强>
答案 4 :(得分:0)
您可以使用此正则表达式:
(?<Month>[A-Z]{3})\s(?<Day>[0-9]{1,2})\s(?<Hour>[0-9]{1,2}):(?<Minute>[0-9]{1,2}):(?<Second>[0-9]{1,2})\s<(?<Login>[^>]+)>(?<Rest>.*)
这有点笨拙和复杂,但我希望下面的例子可以让你得到你想要的。
class Foo
{
public string Month { get; set; }
public int Day { get; set; }
public int Hour { get; set; }
public int Minute { get; set; }
public int Second { get; set; }
public string Login { get; set; }
public string Rest { get; set; }
}
string strRegex = @"(?<Month>[A-Z]{3})\s(?<Day>[0-9]{1,2})\s(?<Hour>[0-9]{1,2}):(?<Minute>[0-9]{1,2}):(?<Second>[0-9]{1,2})\s<(?<Login>[^>]+)>(?<Rest>.*)";
RegexOptions myRegexOptions = RegexOptions.None;
Regex myRegex = new Regex(strRegex, myRegexOptions);
string strTargetString = @"JAN 01 00:00:01 <Admin> Action, May have spaces etc. \n";
foreach (Match myMatch in myRegex.Matches(strTargetString))
{
if (myMatch.Success)
{
new Foo
{
Month = myMatch.Groups["Month"].Value,
Day = Convert.ToInt32(myMatch.Groups["Day"].Value),
Hour = Convert.ToInt32(myMatch.Groups["Hour"].Value),
Minute = Convert.ToInt32(myMatch.Groups["Minute"].Value),
Second = Convert.ToInt32(myMatch.Groups["Second"].Value),
Login = myMatch.Groups["Login"].Value,
Rest = myMatch.Groups["Rest"].Value
}
}
}
答案 5 :(得分:0)
以下正则表达式将起到作用。
^([A-Z]{3})\s*([0-9]{1,2})\s*([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})\s*<(.+)>\s*(.+)
使用在线regex builder进行测试。
它将返回7个被捕获的组。