【问题标题】:Regex split mac OSX output in C#正则表达式在 C# 中拆分 mac OSX 输出
【发布时间】:2020-12-18 13:45:30
【问题描述】:

我正在尝试拆分出现在 Mac OSX 日志文件中的 df -h 命令的输出,该行如下所示:

//user@192.168.0.10/share  3.6Ti  1.0Ti  2.7Ti    28% 264402606  712347471   27%   /private/tmp/mount something here

我需要的是输出

//user@192.168.0.10/share
3.6Ti
1.0Ti
2.7Ti
28%
264402606
712347471
27%
/private/tmp/mount something here

由于最终条目中出现空格,我无法拆分此内容,因此我不太确定如何处理。

任何建议将不胜感激。

--更新--

感谢您的所有意见,这是我想出的解决方案:

var fields = Regex.Split(line, @"[ ]{2,}|(?<=\d+\%?)\s+(?=\d+\%?)")?.ToList();

我会看看建议的答案,谢谢

【问题讨论】:

  • 这一行的结构是多少常量或变量?哪些部分保持不变,哪些可以改变?以什么方式?
  • 结构始终相同,但值可以改变。所以它总是以主机开始,然后是数值,以路径结束,但路径中可能有也可能没有空格
  • 你有没有尝试过?您甚至不需要正则表达式,因为列是固定的并且值是右对齐的。您可以阅读第一行以确定每列的开始位置,然后直接读取子字符串
  • 我尝试了各种不同的正则表达式,但它们都错误地分割了空格。另外,列的间距并不总是相等的,如果你看的话,有时会有多个空格分隔值。
  • " 另外,列的间距并不总是相等的,如果您看有时会有多个空格分隔值”,所以这些空格可以从一个日志行到另一个日志行有所不同?我们只看到 1 个日志行。但我们询问的是不同的日志行版本

标签: c# .net regex


【解决方案1】:

我修改了我的答案,但 Dans solution 看起来仍然更好

如何:

这只有在路径外的空格数永远不会改变时才有效。首先,我拆分字符串并从数组中删除所有空条目。然后我计算我的数组的条目,因为索引 8 之后的每个条目都属于路径。然后我将这些条目与空格重新组合在一起以完成路径。

代码:

string log = "//user@192.168.0.10/share  3.6Ti  1.0Ti  2.7Ti    28% 264402606  712347471   27%   /private/tmp/mount something here";
string[] logSplit = log.Split(' ');

//Remove empty strings
logSplit = logSplit.ToList().Where(x => !string.IsNullOrWhiteSpace(x)).ToArray();

//Put the path back together
int index = 0;
foreach(string logPart in logSplit)
{
    if(index >= 9)
    {
        logSplit[8] = logSplit[8] + " " + logSplit[index];
        logSplit = logSplit.ToList().Where(x => x != logPart).ToArray();
    }
    else
    {
        index++;
    }
}

【讨论】:

  • 可能无法保证“路径”部分一次不会超过 1 个空格...
【解决方案2】:

这是我使用 Regex.Split 的方法。

string[] parts = Regex.Split(input, @"\s+(?=/)");
string[] fields = Regex.Split(parts[0], @"\s+");

这是一个完整注释的解释:

string input = @"//user@192.168.0.10/share  3.6Ti  1.0Ti  2.7Ti    28% 264402606  712347471   27%   /private/tmp/mount something here";

// Split the string into two parts where you have spaces followed by a `/`
// The second part will be the filename
// As for the first part, we will need to process it further.
string[] parts = Regex.Split(input, @"\s+(?=/)");
// parts[0]: "//user@192.168.0.10/share  3.6Ti  1.0Ti  2.7Ti    28% 264402606  712347471   27%"
// parts[1]: "/private/tmp/mount something here"

// Split the first part on spaces to get all the other fields.
string[] fields = Regex.Split(parts[0], @"\s+");
// fields[0]: "//user@192.168.0.10/share"
// fields[1]: "3.6Ti"
// fields[2]: "1.0Ti"
// fields[3]: "2.7Ti"
// fields[4]: "28%"
// fields[5]: "264402606"
// fields[6]: "712347471"
// fields[7]: "27%"

string filename = parts[1]; // parts[1] is the filename

【讨论】:

    【解决方案3】:

    我不确定您使用的是什么正则表达式引擎,但我认为这应该可以满足您的需求。这里的技巧是交流发电机,在一组空格或 /private 上拆分,然后一直到行尾。

    \s+|(/private.*)
    

    更新: 用代码去除任何空行。

    var fields = Regex.Split(input, @"\s+|(/private.*)").Select(str => !string.IsNullOrWhiteSpace(str)).ToList();
    

    【讨论】:

    • 如果你使用Regex.Split,它会在路径前后发出一个空字符串。
    • 问题大吗?您应该能够相当容易地以编程方式删除空行。对于之前的空字符串,我认为这是让 2 个拆分器彼此相邻的副作用。最后,它可能是从回车或其他东西中分离出来的。我不确定。
    • 不,不难。在答案中包含该代码可能会很好。您编写的实际代码可能类似于:string[] fields = Regex.Split(input, @"\s+|(/private.*)").Where(str =&gt; !string.IsNullOrEmpty(str)).ToArray();
    • 好的,当然。我最初只是认为它超出了此范围,但我很高兴将其包括在内。我已经更新了我的答案,这与您写的非常相似。
    【解决方案4】:

    Regex 只是一个工具,即使它可以满足您的需求......我会以其他更容易理解的方式(至少对我而言)。

    这是我提出的解决方案,使用字符串拆分和一些循环。它不对任何地方的空间数量做任何假设;路径开始前的多个空格被删除,路径内的多个空格被保留,以防万一。

    var s = "//user@192.168.0.10/share  3.6Ti  1.0Ti  2.7Ti    28% 264402606  712347471   27%   /private/tmp/mount something    here";
    
    var parts = s.Split(' ');
    var index = 0;
    // Find index of first item that starts with a single "/"
    while (parts[index].StartsWith("//") || !parts[index].StartsWith("/"))
        index++;
    
    var result = new List<string>();
    
    // Gather non-empty items, EXcluding the one that starts with a single "/"
    for (var i = 0; i < index; i++)
        if (parts[i].Length > 0) 
            result.Add(parts[i]);
    
    // Rebuild path from all remaining items, including empty ones, adding space characters
    var path = parts[index];
    for (var i = index + 1; i < parts.Length; i++)
        path += " " + parts[i];
    
    result.Add(path);
    

    结果:

    //user@192.168.0.10/share
    3.6Ti
    1.0Ti
    2.7Ti
    28%
    264402606
    712347471
    27%
    /private/tmp/mount something    here
    

    工作演示,使用包含多个空格的路径的日志字符串:
    https://dotnetfiddle.net/KMA9Xy

    【讨论】:

      猜你喜欢
      • 2021-03-29
      • 2010-11-03
      • 2021-10-07
      • 2021-12-14
      • 1970-01-01
      • 1970-01-01
      • 2022-08-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多