Разбор файла ASCII на основе позиции и длины в строке с использованием Python - PullRequest
1 голос
/ 17 марта 2012

Я хотел бы конвертировать конкретный файл ASCII в CSV. Этот файл имеет собственную спецификацию, и я публикую ниже соответствующие фрагменты.
строка A начинается с кода 66TP:

66TP        1003    54.437269600149717.012388003107655.5139691177756                :10.008677993245250.01231534739191


строка B начинается с C6NM:

C6NM0821.565823793411260.900167346000671.2812114953994820.81007696688170033                                1679475490.0000000001679475527.0000000001


Как вы видите выше, отдельные значения не разделены, но их дифференциация по положению и длине в строке.

спецификация линии A:

1 Position   Length Data format Description of field

2   1           2   Type code   Record type code = 66
3   3           2   Derivation  Derivation code
4   5           16  Name        Point name
5   21          16  Latitude    Latitude
6   37          16  Longitude   Longitude
7   53          16  Distance    WGS84 ellipsoidal height at APC
8   69          16  Text 16     Feature code
9   85          1   GPS Method  Measurement method
10  86          1   Classification  Classification of the point
11  87          16  Distance    Horizontal precision
12  103         16  Distance    Vertical precision


спецификация линии B:

1   Position Length Data format Description of field
2   1           2   Type code   Record type code = C6
3   3           2   Derivation  Derivation code
4   5           2   Integer 2   Minimum number of satellites
5   7           1   Boolean     Relative DOPs
6   8               16  Scalar  PDOP (maximum)
7   24          16  Scalar  HDOP (maximum)
8   40          16  Scalar  VDOP (maximum)
9   56          16  Scalar  RMS
10  72          4   Integer 4   Number of GPS positions used
11  76          16  Distance    Horizontal standard deviation
12  92          16  Distance    Vertical standard deviation
13  108         4   Integer 4   Start GPS week
14  112         16  Scalar  Start GPS time in seconds to 3dp
15  128         4   Integer 4   End GPS Week
16  132         16  Scalar  End GPS time in seconds to 3dp
17  148         1   Monitor Status


Мой желаемый результат - объединить обе строки и будет выглядеть так:

1003,54.4372696001497,17.0123880031076,55.5139691177756,0.009,0.012,8,1.6,0.9,1.28,20.8,033,1679,475490.0,1679,475527.0


и вот входной файл, где я пометил отдельные значения в квадратных скобках:

66TP        [1003]    [54.4372696001497][17.0123880031076][55.5139691177756]                :1[0.00867799324525][0.01231534739191]

C6NM[082][1.56582379341126][0.90016734600067][1.28121149539948][20.81007696688170][033]                                [1679][475490.000000000][1679][475527.0000000001]


Извините за довольно длинный пост, но я понятия не имею, как я могу описать это в более краткой форме. Я начинающий программист-любитель, и я хотел бы попросить вас дать нам подсказку, которая позволила бы мне начать обработка данных такого типа.

Ответы [ 3 ]

2 голосов
/ 17 марта 2012

Поскольку вы знаете положение каждого элемента в каждой строке, используйте строковый фрагмент , чтобы захватить каждый элемент.

Например,

type_code = linea[0:2]
(derivation, name) = (linea[2:4], linea[4:20])

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

Код

def split_string_by_position(a_string, lengths):
    result = []
    position = 0
    for length in lengths:
        result.append(a_string[position:position+length])
        position = position+length
    return result


line = '66TP        1003    54.437269600149717.012388003107655.5139691177756'
lengths = [2, 2, 16, 16, 16, 16, 16, 16, 1, 1, 16, 16]

print(split_string_by_position(line, lengths))

выход

['66', 'TP', '        1003    ', '54.4372696001497', '17.0123880031076', '55.5139691177756', '', '', '', '', '', '']

Это просто возвращает список элементов данных. Вы могли бы сделать этот шаг дальше, указав имя переменной вместе с каждой длиной ([[2,'type'], [2,'derivation'],...]) и немного изменить функцию, чтобы она вместо этого возвращала dict, чтобы вы могли получить к ней доступ, используя the_result['variable_name']

Несколько идей для игры. http://learnpythonthehardway.org/ было бы хорошо для вас проработать, чтобы вы изучили основы языка.

1 голос
/ 04 февраля 2014

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

Первый код:

  1 #!/usr/bin/env python
  2
  3 def parser(str,len):
  4     '''Generate parsed chunks from str based on a list of lengths, len'''
  5     position = 0
  6     for l in len:
  7         yield str[position:position+l]
  8         position = position + l
  9
 10 line = '66TP        1003    54.437269600149717.012388003107655.5139691177756'
 11 lengths = [2, 2, 16, 16, 16, 16, 16, 16, 1, 1, 16, 16]
 12
 13 lines = [ chunk for chunk in parser(line, lengths) ]
 14 print lines

Теперь вы можете использовать свой парсер везде, где можете использовать итератор; например, как я использовал его в строке 13, чтобы поместить все строки в список, называемый строками.

Вы также можете изменить свой генератор интересными способами, такими как добавление .strip () в конец строки 7. Теперь у ваших полей пропущены пробелы в передней и задней части каждого.

Со строкой 7, измененной, как описано:

        yield str[position:position+l].strip()

Теперь вы получаете измененный вывод:

['66', 'TP', '1003', '54.4372696001497', '17.0123880031076', '55.5139691177756', '', '', '', '', '', '']
1 голос
/ 17 марта 2012

Похоже, это разделено пробелами, в этом случае вы можете игнорировать номера столбцов и просто использовать line.split (), чтобы получить список полей.

Моя программа для работы с таблицамиможет также помочь: http://stromberg.dnsalias.org/~strombrg/to-table.html

...