Pythonic способ извлечения значений из этого текстового файла
У меня есть выходной файл из устаревшего программного обеспечения, который показан ниже. Я хочу извлечь из него значения, чтобы, например, я мог установить переменную direct_solar_irradiance
в 648.957
, а target ground pressure
в 1013.00
.
До сих пор я извлекал отдельные строки и обрабатывал их, как показано ниже (повторяя много раз для различных значений, которые я хочу извлечь):
values = lines[97].split()
self.irradiance_direct, self.irradiance_diffuse, self.irradiance_env = values
Однако теперь я обнаружил, что дополнительные строки добавляются в середину вывода при выборе определенных параметров. Это означает, конечно, что 97-я строка больше не будет иметь тех значений, которые мне нужны.
Есть ли хороший Питонский способ извлечь эти значения, учитывая, что при определенных обстоятельствах в выходные данные могут быть добавлены дополнительные строки? Я думаю, что мне нужно искать известные фрагменты текста в файле, а затем извлекать числа, на которые они ссылаются, но единственные способы, которые я могу придумать, это очень неуклюжие.
Итак:
-
Есть ли хороший Питонский способ поиска эти строки и извлекать значения, которые я хочу?
-
Если нет, то есть ли какой-то другой способ сделать это разумно? (например, какая-то классная библиотека синтаксического анализа текстовых файлов, о которой я ничего не знаю).
******************************* 6sV version 1.0B ****************************** * * * geometrical conditions identity * * ------------------------------- * * user defined conditions * * * * month: 14 day : 1 * * solar zenith angle: 10.00 deg solar azimuthal angle: 20.00 deg * * view zenith angle: 30.00 deg view azimuthal angle: 40.00 deg * * scattering angle: 159.14 deg azimuthal angle difference: 20.00 deg * * * * atmospheric model description * * ----------------------------- * * atmospheric model identity : * * midlatitude summer (uh2o=2.93g/cm2,uo3=.319cm-atm) * * aerosols type identity : * * Maritime aerosol model * * optical condition identity : * * visibility : 8.49 km opt. thick. 550 nm : 0.5000 * * * * spectral condition * * ------------------ * * monochromatic calculation at wl 0.400 micron * * * * Surface polarization parameters * * ---------------------------------- * * * * * * Surface Polarization Q,U,Rop,Chi 0.00000 0.00000 0.00000 0.00 * * * * * * target type * * ----------- * * homogeneous ground * * monochromatic reflectance 1.000 * * * * target elevation description * * ---------------------------- * * ground pressure [mb] 1013.00 * * ground altitude [km] 0.000 * * * * plane simulation description * * ---------------------------- * * plane pressure [mb] 1013.00 * * plane altitude absolute [km] 0.000 * * atmosphere under plane description: * * ozone content 0.000 * * h2o content 0.000 * * aerosol opt. thick. 550nm 0.000 * * * * atmospheric correction activated * * -------------------------------- * * BRDF coupling correction * * input apparent reflectance : 0.500 * * * ******************************************************************************* ******************************************************************************* * * * integrated values of : * * -------------------- * * * * apparent reflectance 1.1287696 appar. rad.(w/m2/sr/mic) 588.646 * * total gaseous transmittance 1.000 * * * ******************************************************************************* * * * coupling aerosol -wv : * * -------------------- * * wv above aerosol : 1.129 wv mixed with aerosol : 1.129 * * wv under aerosol : 1.129 * ******************************************************************************* * * * integrated values of : * * -------------------- * * * * app. polarized refl. 0.0000 app. pol. rad. (w/m2/sr/mic) 0.000 * * direction of the plane of polarization 0.00 * * total polarization ratio 0.000 * * * ******************************************************************************* * * * int. normalized values of : * * --------------------------- * * % of irradiance at ground level * * % of direct irr. % of diffuse irr. % of enviro. irr * * 0.351 0.354 0.295 * * reflectance at satellite level * * atm. intrin. ref. background ref. pixel reflectance * * 0.000 0.000 1.129 * * * * int. absolute values of * * ----------------------- * * irr. at ground level (w/m2/mic) * * direct solar irr. atm. diffuse irr. environment irr * * 648.957 655.412 544.918 * * rad at satel. level (w/m2/sr/mic) * * atm. intrin. rad. background rad. pixel radiance * * 0.000 0.000 588.646 * * * * * * sol. spect (in w/m2/mic) * * 1663.594 * * * ******************************************************************************* ******************************************************************************* * * * integrated values of : * * -------------------- * * * * downward upward total * * global gas. trans. : 1.00000 1.00000 1.00000 * * water " " : 1.00000 1.00000 1.00000 * * ozone " " : 1.00000 1.00000 1.00000 * * co2 " " : 1.00000 1.00000 1.00000 * * oxyg " " : 1.00000 1.00000 1.00000 * * no2 " " : 1.00000 1.00000 1.00000 * * ch4 " " : 1.00000 1.00000 1.00000 * * co " " : 1.00000 1.00000 1.00000 * * * * * * rayl. sca. trans. : 0.84422 1.00000 0.84422 * * aeros. sca. " : 0.94572 1.00000 0.94572 * * total sca. " : 0.79616 1.00000 0.79616 * * * * * * * * rayleigh aerosols total * * * * spherical albedo : 0.23410 0.12354 0.29466 * * optical depth total: 0.36193 0.55006 0.91199 * * optical depth plane: 0.00000 0.00000 0.00000 * * reflectance I : 0.00000 0.00000 0.00000 * * reflectance Q : 0.00000 0.00000 0.00000 * * reflectance U : 0.00000 0.00000 0.00000 * * polarized reflect. : 0.00000 0.00000 0.00000 * * degree of polar. : nan 0.00 nan * * dir. plane polar. : -45.00 -45.00 -45.00 * * phase function I : 1.38819 0.27621 0.71751 * * phase function Q : -0.09117 -0.00856 -0.04134 * * phase function U : -1.34383 0.02142 -0.52039 * * primary deg. of pol: -0.06567 -0.03099 -0.05762 * * sing. scat. albedo : 1.00000 0.98774 0.99261 * * * * * ******************************************************************************* ******************************************************************************* ******************************************************************************* * atmospheric correction result * * ----------------------------- * * input apparent reflectance : 0.500 * * measured radiance [w/m2/sr/mic] : 260.747 * * atmospherically corrected reflectance * * Lambertian case : 0.52995 * * BRDF case : 0.52995 * * coefficients xa xb xc : 0.00241 0.00000 0.29466 * * y=xa*(measured radiance)-xb; acr=y/(1.+xc*y) *
5 ответов:
Вы могли бы бросить свой собственный мини-язык, то есть автоматизировать извлечение. Я сделал следующее, чтобы автоматизировать разбор проприетарной программы-output
# will match in the order written here tokens = ["num_ref_frames", "Max QP", "Min QP", "Avg QP", "I4x4", "I16x16", "SkipZero", "SkipMV", "16x16", "16x8", "8x16", "8x8", "8x4", "4x8", "4x4"] special = ["Quarterpel MVs"] # this dictionary (hash-table) contains the search string from tokens array # as well as an array where the first element is the field to extract to # create matrix array. e.g. 0 = 1st field, 1 = 2nd field, 3 = 3rd field etc. dict = {tokens[0]: [1], tokens[1]: [1], tokens[2]: [1], tokens[3]: [1], tokens[4]: [2], tokens[5]: [2], tokens[6]: [2], tokens[7]: [2], tokens[8]: [2], tokens[9]: [2], tokens[10]: [2], tokens[11]: [2], tokens[12]: [2], tokens[13]: [2], tokens[14]: [2],}
Затем я просто прошелся по входу и для каждой строки проверил содержимое
token
; если совпадение найдено, я сделал разбиение в соответствии с записью dict, чтобы извлечь правильное поле.
special
выше было обрабатывать, ну специальную переменную, которая требовала чтения из нескольких линии.Обновить
Клонировать
git://gist.github.com/1037403.git
, чтобы получить копию кодаusage: ./parser.py all_dec.txt
Надеюсь, это поможет!
Более полное, возможно, более надежное решение потребует использования либо синтаксического анализатора, использующего пользовательский Граммер ( pyparsing), либо какого-либо процессора на основе FSM ( TextFSM).
Оба варианта, как они будут нетривиальны для использования с этим выходом. (Возможно) более легким решением было бы идентифицировать каждую строку на основе известных этикеток, а затем извлечь соответствующим образом (как это предлагается другими плакатами).
Есть несколько способов реализовать это. Я бы предложил сопоставление вызываемых объектов 'extractor' с известными метками строк, затем повторите и вызовите соответствующие экстракторы. Каждый вызываемый объект будет принимать строку и объект контекста / dict в качестве аргументов и добавлять атрибуты в контекст по мере необходимости. Что-то вроде https://gist.github.com/1035938
Ну, если вы хотите универсальную библиотеку синтаксического анализа, есть pyparsing, но в этом случае это, вероятно, будет излишним.
Это, по-видимому, довольно линейно ориентированный текстовый файл, который не так уж велик по размеру, поэтому вам лучше всего будет перебирать каждую строку в поисках текста, который идентифицирует то, что вы ищете.
Итак, что-то вроде:
{[0]}
Затем вы можете добавить дополнительные операторы if и так далее по мере необходимости, чтобы получить другие данные. Хотя, если у вас есть получив много данных, вы, вероятно, захотите несколько обобщить код. (Возможно, словарь с текстом, который должен совпадать в качестве ключа, и функция, вызываемая при совпадении ключа).
Вы также можете использовать регулярное выражение, чтобы соответствовать строке, так что вы можете обрабатывать различные количества пробелов лучше. В противном случае просто один пробел слишком много или слишком мало будет выбрасывать его.
Лучший способ, ИМХО было бы использовать файл mmaped, а затем использовать регулярное выражение, чтобы найти то, что вы ищете.
Модуль Mmap отображает файл как текст, так что вы можете выполнять практически любые операции, которые вы бы выполнили со строкой. А регулярное выражение-это лучший способ что-то искать. Просто и эффективно.text = mmap.mmap(file) re.sub(pattern, text)
Если вам нужно найти определенные строки, просто обрабатывайте все как строку и запускайте определенные регулярные выражения, чтобы выкопать ваши драгоценные камни.
Если вам нужно извлечь больше данных, я считаю, что с небольшим количеством работы вы можете создать хороший парсер для ваших данных. Для начала я бы использовал следующие функции:
def extract_screens(text): """ Returns a list of screens (divided by astericks). Each screen is a list of strings stripped from asterisks. """ ... def process_screen(screen): """ Returns a list of screen divisions as tuples: [(heading, body)...] heading is a string, body is a list of strings blank lines are filtered out. """ ...
Теперь у вас должен быть индексированный список фрагментов текста. Вы можете перебирать их и выполнять простой и специфичный специальный метод парсера для каждого из них раздел.
Совет: используйте модульные тесты, чтобы оставаться в здравом уме.