查找字符串中的字符索引

时间:2010-10-22 20:02:27

标签: c# vb.net

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

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

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中“F”之前的最后一个空格。

我想我还应该提到,每天的列可能并不总是以相同的顺序排列,但它们将具有相同的标题名称。

有关如何在VB.net或c#中执行此操作的任何想法?我知道我可以使用string.indexOf(“JOB_NO”)来获取列开头的索引,但是如何获取每列中最后一个空格的索引? (或在下一个表示下一列开始的第一个非空格之前的最后一个空格)

3 个答案:

答案 0 :(得分:2)

获取所有列的索引。例如

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

然后在数组中对它们进行排序。从最小到最大现在您知道了您的列顺序。第一列的最后一个空格是[the_next_column's_index] -1。

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

答案 1 :(得分:0)

previous answer I've given大量借用...为了获得列位置,这个怎么样?我假设列名不包含空格。

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();

答案 2 :(得分: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