C# 统计列表中字符串的出现次数并在控制台中显示
我现在正在创建一个Logparser,我能够逐行检查文件夹中的所有文件,并提取我想要的子字符串,它是C# 统计列表中字符串的出现次数并在控制台中显示,c#,linq,file,C#,Linq,File,我现在正在创建一个Logparser,我能够逐行检查文件夹中的所有文件,并提取我想要的子字符串,它是“fct=“之后的值。所有这些都使用Regex,我将结果放入列表中。 现在我想计算列表中每个字符串的出现次数并显示它 我使用的是GroupBy,但当我显示结果时,所有出现的内容都在1 实际值: 720 1x 720 1x 710 1x class Program { static void Main(string[] args) { int cou
“fct=“
之后的值。所有这些都使用Regex
,我将结果放入列表中。
现在我想计算列表中每个字符串的出现次数并显示它
我使用的是GroupBy,但当我显示结果时,所有出现的内容都在1
实际值:
720 1x
720 1x
710 1x
class Program
{
static void Main(string[] args)
{
int counter = 0;
string[] dirs = Directory.GetFiles(@"C:/LogParser/LogParserV1", "*.txt");
StreamWriter sw = new StreamWriter("C:/LogParser/LogParserV1/test.txt");
char[] delimiters = { '<', ',', '&', ':', ' ', '\\', '\'' };
string patternfct = "(?<=FCT=)[0-9]*";
foreach (string fileName in dirs)
{
StreamReader sr = new StreamReader(fileName);
{
String lineRead;
while ((lineRead = sr.ReadLine()) != null)
{
//To find all the value of fct= occurence
var listfct = Regex.Matches(lineRead, patternfct,
RegexOptions.IgnoreCase).Cast<Match>().Select(x => x.Value).ToList();
var fctGroups = listfct.GroupBy(i => i);
foreach (var grp in fctGroups)
{
var fct = grp.Key;
var total = grp.Count();
System.Console.WriteLine("fct=" + fct + " " + "Total=" + total);
}
counter++;
}
System.Console.WriteLine(fileName);
sr.Close();
sw.Close();
}
}
// Suspend the screen.
System.Console.ReadLine();
}
}
}
FCT=10019 2x
FCT=4515 1x
它应该是:
720 2x
710 1x
我发现问题在于我逐行读取文件,因此如果同一行上的“fct=“
值不是两次,则不会将其计算为2
,而是仅将其显示的每一行计算为1
所以我需要找到一种方法来计算我的列表,而不是一行一行地计算我的文件
我真的是初学者,所以不知道如何做到这一点,任何提示将被感激
以下是日志数据示例:
<dat>FCT=10019,XN=KEY,CN=ROHWEPJQSKAUMDUC</dat></logurl>
<dat>XN=KEY,CN=RTU FCT=4515</dat>LBZ=test.sqi</logurl>
<dat>XN=KEY,CN=RT</dat>FCT=10019</logurl>
我的代码:
720 1x
720 1x
710 1x
class Program
{
static void Main(string[] args)
{
int counter = 0;
string[] dirs = Directory.GetFiles(@"C:/LogParser/LogParserV1", "*.txt");
StreamWriter sw = new StreamWriter("C:/LogParser/LogParserV1/test.txt");
char[] delimiters = { '<', ',', '&', ':', ' ', '\\', '\'' };
string patternfct = "(?<=FCT=)[0-9]*";
foreach (string fileName in dirs)
{
StreamReader sr = new StreamReader(fileName);
{
String lineRead;
while ((lineRead = sr.ReadLine()) != null)
{
//To find all the value of fct= occurence
var listfct = Regex.Matches(lineRead, patternfct,
RegexOptions.IgnoreCase).Cast<Match>().Select(x => x.Value).ToList();
var fctGroups = listfct.GroupBy(i => i);
foreach (var grp in fctGroups)
{
var fct = grp.Key;
var total = grp.Count();
System.Console.WriteLine("fct=" + fct + " " + "Total=" + total);
}
counter++;
}
System.Console.WriteLine(fileName);
sr.Close();
sw.Close();
}
}
// Suspend the screen.
System.Console.ReadLine();
}
}
}
FCT=10019 2x
FCT=4515 1x
类程序
{
静态void Main(字符串[]参数)
{
int计数器=0;
字符串[]dirs=Directory.GetFiles(@“C:/LogParser/LogParserV1”,“*.txt”);
StreamWriter sw=新的StreamWriter(“C:/LogParser/LogParserV1/test.txt”);
char[]分隔符={'x.Value).ToList();
var fctGroups=listfct.GroupBy(i=>i);
foreach(fctGroups中的var grp)
{
var fct=grp.Key;
var total=grp.Count();
System.Console.WriteLine(“fct=“+fct+”+“Total=“+Total”);
}
计数器++;
}
System.Console.WriteLine(文件名);
高级关闭();
sw.Close();
}
}
//暂停屏幕。
System.Console.ReadLine();
}
}
}
您可以尝试在Linq的帮助下查询数据:
using System.Linq;
using System.Text.RegularExpressions;
...
Regex regex = new Regex("(?<=FCT=)[0-9]*", RegexOptions.IgnoreCase);
var records = Directory
.EnumerateFiles(@"C:/LogParser/LogParserV1", "*.txt")
.SelectMany(file => File.ReadLines(file))
.SelectMany(line => regex
.Matches(line)
.Cast<Match>()
.Select(match => match.Value))
.GroupBy(number => number)
.Select(group => $"FCT={group.Key} {group.Count()}x");
foreach (string record in records)
Console.WriteLine(record);
但是添加了测试行
string[] testLines = new string[] {
"<dat>FCT=10019,XN=KEY,CN=ROHWEPJQSKAUMDUC</dat></logurl>",
"<dat>XN=KEY,CN=RTU FCT=4515</dat>LBZ=test.sqi</logurl>",
"<dat>XN=KEY,CN=RT</dat>FCT=10019</logurl>",
};
Regex regex = new Regex("(?<=FCT=)[0-9]*", RegexOptions.IgnoreCase);
var records = testLines
.SelectMany(line => regex
.Matches(line)
.Cast<Match>()
.Select(match => match.Value))
.GroupBy(number => number)
.Select(group => $"FCT={group.Key} {group.Count()}x");
foreach (string record in records)
Console.WriteLine(record);
编辑:如果要在记录中包含文件
,可以使用匿名对象:
var records = Directory
.EnumerateFiles(@"C:/LogParser/LogParserV1", "*.txt")
.SelectMany(file => File
.ReadLines(file)
.Select(line => new {
file = file,
line = line,
}))
.SelectMany(item => regex
.Matches(item.line)
.Cast<Match>()
.Select(match => new {
file = item.file,
number = match.Value
}))
.GroupBy(item => new {
file = item.file,
number = item.number
})
.OrderBy(group => group.Key.file)
.ThenBy(group => group.Key.number)
.Select(group => $"{group.Key.file} has FCT={group.Key.number} {group.Count()}x")
var记录=目录
.Enumerate文件(@“C:/LogParser/LogParserV1”,“*.txt”)
.SelectMany(文件=>file
.ReadLines(文件)
.选择(行=>新建{
file=file,
行=行,
}))
.SelectMany(项=>regex
.匹配项(项.行)
.Cast()
.选择(匹配=>新建){
file=item.file,
数字=匹配。值
}))
.GroupBy(项目=>新建){
file=item.file,
编号=项目编号
})
.OrderBy(group=>group.Key.file)
.ThenBy(group=>group.Key.number)
.Select(group=>$“{group.Key.file}具有FCT={group.Key.number}{group.Count()}x”)
您能提供您正在解析的日志数据吗?这样您的代码就可以逐行计算您的文本了。你想一个文件一个文件地数数吗?您只需要有一个局部变量countText,并在while循环中累积它countText+=grp.Count()@乔尔·德斯劳瑞尔:很抱歉我的打字错误,它应该是.EnumerateFiles
而不是EnumerateDirectory
我只看到一件似乎不起作用的事情,我需要FCT=忽略我以前使用的区分大小写的RegexOptions。Ignorecase但我似乎无法将它放在您的查询中任何想法?@Joel Deslauriers:Regex Regex=new Regex(“(?很好,它工作得很好,但我也能够使用Directory.GetFiles获得每个文件的名称。您知道我是否可以对EnumerateFiles执行相同的操作吗?EnumerateFiles
一个接一个地返回文件,此时GetFiles
获取所有文件并将其作为数组返回。我们不想等到所有文件都已获取(GetFiles
)我们可以从第一个文件开始(EnumerateFiles
)