2010-10-22 3 views
2

У меня есть текстовый файл, который автоматически генерируется старой компьютерной системой ежедневно.Поиск индекса символов в строке

К сожалению, столбцы в этом файле не ограничены, и они не являются точно фиксированной шириной (каждый день ширина каждого столбца может меняться в зависимости от количества символов данных в каждом столбце). Файл имеет заголовки столбцов, поэтому я хочу найти ширину каждого столбца, используя заголовки столбцов. Вот пример из столбца строки заголовка:

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

То, что я хочу сделать, это получить индекс первого гольца в колонке, а индекс последнего белого пространства колонки (из заголовка столбца). Я хотел бы получить индекс «J» в JOB_NUM и последнее пробел перед «F» в FILE_NAME для первого столбца.

Я думаю, я должен также упомянуть, что столбцы могут не всегда находиться в одном порядке со дня на день, но они будут иметь одинаковые имена заголовков.

Любые мысли о том, как это сделать в VB.net или C#? Я знаю, что могу использовать string.indexOf ("JOB_NO"), чтобы получить индекс начала столбца, но как получить индекс последнего пробела в каждом столбце? (или последние пробелы перед следующим первым не-пробелом, обозначающим начало следующего столбца)

+0

Есть ли acctualy [], или это просто пример того, где находится остроумное пространство. – rerun

+0

нет нет []. Это просто пример того, где находится пустое пространство. – avword

ответ

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

Прошу прощения, мне трудно понять, как использовать вывод этого выражения. Возвращает ли значение «новое Regex ...» значение? – avword

+0

Я переписал свой ответ, чтобы дать понять, что происходит. Нет необходимости создавать новое Regex для получения MatchCollection, но да ... «new Regex» возвращает новый экземпляр Regex, на который я вызывал метод Matches. Поскольку у Regex есть статический метод Matches, скорее всего, лучше использовать его. Результатом выражения является IEnumerable . (Я указал это в моем редактировании). Вы можете вызвать 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 
Смежные вопросы