Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 尽可能长地将行与固定列匹配_C#_Regex_Parsing_Text Parsing_String Parsing - Fatal编程技术网

C# 尽可能长地将行与固定列匹配

C# 尽可能长地将行与固定列匹配,c#,regex,parsing,text-parsing,string-parsing,C#,Regex,Parsing,Text Parsing,String Parsing,我将解析一个遗留系统中的位置基文件。文件中的每一列都有固定的列宽,每一行的最大长度为80个字符。问题是你不知道一排有多长。有时他们只填写前五列,有时使用所有列 如果我知道使用的所有80个字符,那么我可以这样做: ^\s* (?<a>\w{3}) (?<b>[ \d]{2}) (?<c>[ 0-9a-fA-F]{2}) (?<d>.{20}) ... 我应该如何设计正则表达式来匹配它 编辑1 在本例中,我要解析的每一行都以AQM开头 列a

我将解析一个遗留系统中的位置基文件。文件中的每一列都有固定的列宽,每一行的最大长度为80个字符。问题是你不知道一排有多长。有时他们只填写前五列,有时使用所有列

如果我知道使用的所有80个字符,那么我可以这样做:

^\s*
 (?<a>\w{3})
 (?<b>[ \d]{2})
 (?<c>[ 0-9a-fA-F]{2})
 (?<d>.{20})
 ...
我应该如何设计正则表达式来匹配它

编辑1

在本例中,我要解析的每一行都以AQM开头

列a始终从位置0开始 b列始终从位置3开始 列c始终从位置5开始 d列始终从位置7开始 如果列未使用其所有空间,则文件中是否有空格 只能修剪使用的最后一列

编辑2 为了让它更清楚,我在这里附上了soem示例,说明了数据可能是什么样子的,列的定义指出,我在问题前面提到的示例被大大简化了

尝试使用?在那些不在那里的小组之后。在这种情况下,如果某个组丢失,您将获得匹配

编辑n,在Sguazz答案之后

我会用

(?<a>AQM)(?<b>[ \d]{2})?(?<c>[ 0-9a-fA-F]{2})?(?<d>.{0,20})?
试着用一种新的方法?在那些不在那里的小组之后。在这种情况下,如果某个组丢失,您将获得匹配

编辑n,在Sguazz答案之后

我会用

(?<a>AQM)(?<b>[ \d]{2})?(?<c>[ 0-9a-fA-F]{2})?(?<d>.{0,20})?

我不确定在这里使用regexp是否正确。如果我理解你的结构,你想要

if (length >= 8) 
   d = everything 8th column on
   remove field d
else
   d = empty

if (length >= 6)
   c = everything 6th column on
   remove field c
else
   c = empty

等。也许一个regexp可以做到这一点,但它可能会相当做作。

我不确定在这里使用regexp是否正确。如果我理解你的结构,你想要

if (length >= 8) 
   d = everything 8th column on
   remove field d
else
   d = empty

if (length >= 6)
   c = everything 6th column on
   remove field c
else
   c = empty

等。也许一个regexp可以做到这一点,但它可能会相当做作。

所以,换句话来说:在你的例子中,你有一个字符序列,你知道前3个属于a组,后面2个属于B组,然后2个属于C组,20个属于D组,但可能没有这么多元素

尝试:

(?<a>\w{0,3})(?<b>[ \d]{0,2})(?<c>[ 0-9a-fA-F]{0,2})(?<d>.{0,20})
基本上,这些数字现在是团体的上限,而不是固定的人数

编辑,以反映您最后的评论:如果您知道所有相关行都以“AQM”开头,您可以将组A替换为?AQM

另一个编辑:让我们试试这个

(?<a>AQM)(?<b>[ \d]{2}|[ \d]$)(?<c>[ 0-9a-fA-F]{0,2})(?<d>.{0,20})

所以,换句话来说:在你的例子中,你有一个字符序列,你知道前3个属于a组,后面2个属于B组,然后2个属于C组,20个属于D组,但可能没有这么多的元素

尝试:

(?<a>\w{0,3})(?<b>[ \d]{0,2})(?<c>[ 0-9a-fA-F]{0,2})(?<d>.{0,20})
基本上,这些数字现在是团体的上限,而不是固定的人数

编辑,以反映您最后的评论:如果您知道所有相关行都以“AQM”开头,您可以将组A替换为?AQM

另一个编辑:让我们试试这个

(?<a>AQM)(?<b>[ \d]{2}|[ \d]$)(?<c>[ 0-9a-fA-F]{0,2})(?<d>.{0,20})

也许您可以使用这样的函数将字符串分解为列值。它不解析注释字符串,并且能够处理少于80个字符的字符串。但它不会验证列的内容。当你使用这些值时,也许你可以做到这一点

/// <summary>
/// Break a data row into a collection of strings based on the expected column widths.
/// </summary>
/// <param name="input">The width delimited input data to break into sub strings.</param>
/// <returns>
/// An empty collection if the input string is empty or a comment.
/// A collection of the width delimited values contained in the input string otherwise.
/// </returns>
private static IEnumerable<string> ParseRow(string input) {
    const string COMMENT_PREFIX = "COM*";
    var columnWidths = new int[] { 3, 2, 2, 3, 6, 14, 2, 2, 3, 2, 2, 10, 7, 7, 2, 1, 1, 2, 7, 1, 1 };
    int inputCursor = 0;
    int columnIndex = 0;
    var parsedValues = new List<string>();

    if (String.IsNullOrEmpty(input) || input.StartsWith(COMMENT_PREFIX) || input.Trim().Length == 0) {
        return parsedValues;
    }

    while (inputCursor < input.Length && columnIndex < columnWidths.Length) {
        //Make sure the column width never exceeds the bounds of the input string. This can happen if the input string doesn't end on the edge of a column.
        int columnWidth = Math.Min(columnWidths[columnIndex++], input.Length - inputCursor);
        string columnValue = input.Substring(inputCursor, columnWidth);
        parsedValues.Add(columnValue);
        inputCursor += columnWidth;
    }
    return parsedValues;
}

也许您可以使用这样的函数将字符串分解为列值。它不解析注释字符串,并且能够处理少于80个字符的字符串。但它不会验证列的内容。当你使用这些值时,也许你可以做到这一点

/// <summary>
/// Break a data row into a collection of strings based on the expected column widths.
/// </summary>
/// <param name="input">The width delimited input data to break into sub strings.</param>
/// <returns>
/// An empty collection if the input string is empty or a comment.
/// A collection of the width delimited values contained in the input string otherwise.
/// </returns>
private static IEnumerable<string> ParseRow(string input) {
    const string COMMENT_PREFIX = "COM*";
    var columnWidths = new int[] { 3, 2, 2, 3, 6, 14, 2, 2, 3, 2, 2, 10, 7, 7, 2, 1, 1, 2, 7, 1, 1 };
    int inputCursor = 0;
    int columnIndex = 0;
    var parsedValues = new List<string>();

    if (String.IsNullOrEmpty(input) || input.StartsWith(COMMENT_PREFIX) || input.Trim().Length == 0) {
        return parsedValues;
    }

    while (inputCursor < input.Length && columnIndex < columnWidths.Length) {
        //Make sure the column width never exceeds the bounds of the input string. This can happen if the input string doesn't end on the edge of a column.
        int columnWidth = Math.Min(columnWidths[columnIndex++], input.Length - inputCursor);
        string columnValue = input.Substring(inputCursor, columnWidth);
        parsedValues.Add(columnValue);
        inputCursor += columnWidth;
    }
    return parsedValues;
}

你的要求不是很清楚。示例中的哪些行应该匹配,哪些不应该匹配?为什么?对不起。示例中的所有行都应该匹配。任务是获取每行上存在的所有列。我添加了更多的示例来显示不匹配的行。在您的情况下,主要问题是列之间缺少任何清晰的分隔符。由于每列中的字符数都是可变的,因此什么可以限定某个字符位于该列或该列中?除最后一列外,每列中的字符数是固定的。最后一列可以修剪。我添加了一个新的例子,列更短,并用空格填补了空白。您的要求并不明确。示例中的哪些行应该匹配,哪些不应该匹配?为什么?对不起。示例中的所有行都应该匹配。任务是获取每行上存在的所有列。我添加了更多的示例来显示不匹配的行。在您的情况下,主要问题是列之间缺少任何清晰的分隔符。由于每列中的字符数都是可变的,因此什么可以限定某个字符位于该列或该列中?除最后一列外,每列中的字符数是固定的。最后一列可以修改。我添加了一个新的例子,列更短,并用spacesOk填补了空白。我编辑,即使你的评论会让以后的读者感到困惑。我尝试过这样做,但是

如果你把最后一个专栏的时间安排好了,会发生什么?在每个组之后,每个列都是可选的。但没有列是可选的。我知道d列总是从第7位开始,如果它存在的话。好的,那么就用?+把它忘了?对于其他组。可能使用\d[\d]而不是[\d]{2},这样消耗的列数是正确的,并且您避免只使用空格。对不起,我太模糊了。我的意思是,它是最后一个可以缩短的使用列。然而,哪一列是未知的。他们可能只会使用前2-3列,你永远不知道。好吧,我编辑,即使你的评论会让人困惑谁会在以后阅读。我已经尝试过这样做,但是当他们对最后一列进行计时时会发生什么,如果你把它放进去?在每个组之后,每个列都是可选的。但没有列是可选的。我知道d列总是从第7位开始,如果它存在的话。好的,那么就用?+把它忘了?对于其他组。可能使用\d[\d]而不是[\d]{2},这样消耗的列数是正确的,并且您避免只使用空格。对不起,我太模糊了。我的意思是,它是最后一个可以缩短的使用列。然而,哪一列是未知的。他们可能只使用前2-3列,你永远不知道。我也想过这样做。问题是你不能保证列的宽度是固定的;其他的则用空格填充,而这些空格实际上只是另一个字符。这不对吗?也许我误解了什么,但我很难找到一个失败的争吵。你能提供一个吗?每行都是匹配的。它是最后一个可以修剪的使用列。但你不知道最新的愿望专栏。我添加了一个不匹配的新示例,我明白了。这个怎么样?我也想过要做这个。问题是你不能保证列的宽度是固定的;其他的则用空格填充,而这些空格实际上只是另一个字符。这不对吗?也许我误解了什么,但我很难找到一个失败的争吵。你能提供一个吗?每行都是匹配的。它是最后一个可以修剪的使用列。但你不知道最新的愿望专栏。我添加了一个不匹配的新示例,我明白了。这个怎么样?