在一个字符串中查找字符的索引

4

我有一个文本文件,是由一台老旧的计算机系统每天自动生成的。

不幸的是,这个文件中的列没有分隔符,而且它们的宽度并不完全固定(每天每列的宽度都可能会因为数据中每列的字符数而改变)。该文件确实有列标题,所以我想使用列标题来找到每列的宽度。以下是列标题行的示例:

JOB_NO[variable amount of white space chars]FILE_NAME[variable amount of ws chars]PROJECT_CODE[variable amount of ws chars][carriage return]

我想要做的是获取一列中第一个字符的索引和最后一个空格的索引(从列标题开始)。我想要获取 JOB_NUM 中的 "J" 的索引和第一列中 FILE_NAME 前面的最后一个空格的索引。

我想提醒一下,这些列可能每天的顺序都不一样,但它们将具有相同的标题名称。

你有没有想法如何在 VB.net 或 c# 中实现这个功能?我知道我可以使用 string.indexOf("JOB_NO") 来获取该列的起始位置索引,但如何获取每列中最后一个空格的索引呢?(或者在下一个非空白符号表示下一列的开头之前的最后一个空格)


这里实际上是否有 [],还是只是用来表示空格的示例? - rerun
不,这里没有[]。那只是一个示例,用来说明空格的位置。 - avword
3个回答

3

获取所有列的索引。例如:

var jPos = str.IndexOf("JOB_NO");
var filePos = str.IndexOf("FILE_NAME");
var projPos = str.IndexOf("PROJECT_CODE");  

将它们在数组中排序,从小到大。现在你知道了列的顺序,第一列最后一个空格是下一列的索引减1。

int firstColLastSpace = ar[1] -1;
int secColLastSpace = ar[2] -1;

0
借鉴我之前给出的答案... 获取列位置,这个怎么样?我假设列名不含空格。
IEnumerable<int> positions=Regex
    .Matches("JOB_NUM   FILE_NAME         SOME_OTHER_THING",@"(?<=^| )\w")
    .Cast<Match>()
    .Select(m=>m.Index);

(以上内容的详细版本)

//first get a MatchCollection
//this regular expression matches a word character that immediately follows
//either the start of the line or a space, i.e. the first char of each of
//your column headers
MatchCollection matches=Regex
    .Matches("JOB_NUM   FILE_NAME         SOME_OTHER_THING",@"(?<=^| )\w");
//convert to IEnumerable<Match>, so we can use Linq on our matches
IEnumerable<Match> matchEnumerable=matches.Cast<Match>();
//For each match, select its Index
IEnumerable<int> positions=matchEnumerable.Select(m=>m.Index);
//convert to array (if you want)
int[] pos_arr=positions.ToArray();

抱歉,我很难弄清楚如何使用该表达式的输出。 "new Regex..." 返回一个值吗? - avword
我已经重写了我的答案,以便清楚地说明正在发生的事情。不需要实例化一个新的Regex来获取MatchCollection,但是...“new Regex”返回一个新的Regex实例,我在其上调用了Matches方法。由于Regex具有静态Matches方法,因此最好使用它。表达式的输出是IEnumerable<int>。(我在我的编辑中指出了这一点)。如果您更喜欢这些类型的集合,可以在其上调用ToList或ToArray。 - spender

0

这里提供了一种使用小类的替代答案,您可以稍后使用它来解析您的行。您可以使用字段集合作为模板来提取每行的字段,此解决方案不会忽略空格,因为我假设它们是可变的,因为每天字段的长度都不同,您需要这些数据:

Imports System.Text.RegularExpressions

Module Module1

    Sub Main()

        Dim line As String = "JOB_NUM      FILE_NAME         SOME_OTHER_THING  "
        Dim Fields As List(Of Field) = New List(Of Field)
        Dim oField As Field = Nothing

        Dim mc As MatchCollection = Regex.Matches(
            line, "(?<=^| )\w")

        For Each m As Match In mc
            oField = New Field
            oField.Start = m.Index
            'Loop through the matches
            If m.NextMatch.Index = 0 Then
                'This is the last field
                oField.Length = line.Length - oField.Start
            Else
                oField.Length = m.NextMatch.Index - oField.Start
            End If
            oField.Name = line.Substring(oField.Start, oField.Length)
            'Trim the field name:
            oField.Name = Trim(oField.Name)
            'Add to the list
            Fields.Add(oField)
        Next

        'Check the Fields: you can use line.substring(ofield.start, ofield.length)
        'to parse each line of your file.

        For Each f As Field In Fields
            Console.WriteLine("Field Name: " & f.Name)
            Console.WriteLine("Start: " & f.Start)
            Console.WriteLine("Length " & f.Length)
        Next

        Console.Read()
    End Sub

    Class Field
        Public Property Name As String
        Public Property Start As Integer
        Public Property Length As Integer
    End Class

End Module

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接