我有一个文本文件,每天由旧计算机系统自动生成。
不幸的是,此文件中的列没有分隔,并且它们的宽度并不完全固定(每一行的宽度可能会根据每列中数据的字符数而改变)。该文件确实有列标题,因此我想使用列标题找到每列的宽度。以下是列标题行的示例:
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”)来获取列开头的索引,但是如何获取每列中最后一个空格的索引? (或在下一个表示下一列开始的第一个非空格之前的最后一个空格)
答案 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