Получить только третий и шестой столбец из выходных данных команды pdffonts - PullRequest
0 голосов
/ 18 декабря 2018

Я использую Poppler pdffonts, чтобы получить шрифты в PDF-документе.Ниже приведен пример вывода

$ pdffonts "some.pdf"
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
TimesNewRoman                        TrueType          WinAnsi          no  no  no      36  0
TimesNewRoman,Bold                   TrueType          WinAnsi          no  no  no      38  0
EDMFMD+Symbol                        CID TrueType      Identity-H       yes yes yes     41  0
Arial                                TrueType          WinAnsi          no  no  no      43  0
Arial,Bold                           TrueType          WinAnsi          no  no  no      16  0

Теперь я хочу получить только значения столбцов "кодировка" и "uni" в выводе выше.Но я не могу получить из-за несогласованности места в каждой строке.

Пробные методы (Python):

1) Разбить каждую строку на пробел, соединить пробелом, а затем разбить, чтобы элементыиндексов 2 и 5 в результирующем списке даст мне необходимые значения для каждой строки.Этот подход не работает из-за пробелов в значениях строк.

Пример кода:

for line in os.popen("pdffonts some.pdf").readlines():
    print ' '.join(line.split()).split()

вывод:

['name', 'type', 'encoding', 'emb', 'sub', 'uni', 'object', 'ID']
['------------------------------------', '-----------------', '----------------', '---', '---', '---', '---------']
['FMGLMO+MyriadPro-Bold', 'Type', '1C', 'Custom', 'yes', 'yes', 'yes', '127', '0']
['FMGMMM+MyriadPro-Semibold', 'Type', '1C', 'Custom', 'yes', 'yes', 'yes', '88', '0']
['Arial-BoldMT', 'TrueType', 'WinAnsi', 'no', 'no', 'no', '90', '0']
['TimesNewRomanPSMT', 'TrueType', 'WinAnsi', 'no', 'no', 'no', '92', '0']
['FMGMHL+TimesNewRomanPSMT', 'CID', 'TrueType', 'Identity-H', 'yes', 'yes', 'no', '95', '0']
['FMHBEE+Arial-BoldMT', 'CID', 'TrueType', 'Identity-H', 'yes', 'yes', 'no', '100', '0']
['TimesNewRomanPS-BoldMT', 'TrueType', 'WinAnsi', 'no', 'no', 'no', '103', '0']

2) Используйте регулярное выражение, чтобы разбить каждую строкувывод с минимум двумя пробелами.Этот подход терпит неудачу, потому что теперь я не могу получить индекс 5, потому что присутствует только один пробел.

Пример кода:

for line in os.popen("pdffonts some.pdf").readlines():
    print re.split(r'\s{2,}', line.strip())

Вывод:

['name', 'type', 'encoding', 'emb sub uni object ID']
['------------------------------------ ----------------- ---------------- --- --- --- ---------']
['FMGLMO+MyriadPro-Bold', 'Type 1C', 'Custom', 'yes yes yes', '127', '0']
['FMGMMM+MyriadPro-Semibold', 'Type 1C', 'Custom', 'yes yes yes', '88', '0']
['Arial-BoldMT', 'TrueType', 'WinAnsi', 'no', 'no', 'no', '90', '0']
['TimesNewRomanPSMT', 'TrueType', 'WinAnsi', 'no', 'no', 'no', '92', '0']
['FMGMHL+TimesNewRomanPSMT', 'CID TrueType', 'Identity-H', 'yes yes no', '95', '0']
['FMHBEE+Arial-BoldMT', 'CID TrueType', 'Identity-H', 'yes yes no', '100', '0']
['TimesNewRomanPS-BoldMT', 'TrueType', 'WinAnsi', 'no', 'no', 'no', '103', '0']

AWK: Ошибка из-за недостатка места. Пожалуйста, сравните с исходным выводом, чтобы получить разницу.

$ pdffonts "some.pdf"|awk '{print $3}'

encoding
----------------
WinAnsi
WinAnsi
TrueType
WinAnsi
WinAnsi

Ответы [ 4 ]

0 голосов
/ 18 декабря 2018

Также с Perl вы можете сделать это, как показано ниже

> cat some.pdf
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
TimesNewRoman                        TrueType          WinAnsi          no  no  no      36  0
TimesNewRoman,Bold                   TrueType          WinAnsi          no  no  no      38  0
EDMFMD+Symbol                        CID TrueType      Identity-H       yes yes yes     41  0
Arial                                TrueType          WinAnsi          no  no  no      43  0
Arial,Bold                           TrueType          WinAnsi          no  no  no      16  0
> perl -lane ' $enc=@F==9? $F[3]:$F[2]; print "$enc\t\t$F[-3]" ' some.pdf
encoding                uni
----------------                ---
WinAnsi         no
WinAnsi         no
Identity-H              yes
WinAnsi         no
WinAnsi         no
> 
0 голосов
/ 18 декабря 2018

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

Удобно, что мы можем найти последовательные "------" во второй строке и вырезать столбцы в начале и в конце каждой последовательности тире.(начиная с " -", заканчивая "- ").

Я написал функцию get_column, которая находит ее по имени столбца.

import os

lines_in = os.popen("pdffonts some.pdf")
# read the column names
header = lines_in.readline();

# read the: --------...
column_dashes = lines_in.readline()

# find column starts and ends
column_starts = [0]
pos = 0
while True:
  pos = column_dashes.find(" -", pos)
  if pos == -1:
    break
  column_starts.append(pos+1)
  pos += 1

column_ends = []
pos = 0
while True:
  pos = column_dashes.find("- ", pos)
  if pos == -1:
    column_ends.append(len(column_dashes))
    break
  column_ends.append(pos+1)
  pos += 1

def get_column( line, name ):
  n = columns[name]
  return line[column_starts[n]:column_ends[n]].strip()

# get column names
columns = {}
for n in range(len(column_starts)):
  columns[ header[column_starts[n]:column_ends[n]].strip() ] = n

# read rest of the table
for line in lines_in.readlines():
  print( (get_column(line,"encoding"), get_column(line, "uni")) )

Результат:

('WinAnsi', 'no')
('WinAnsi', 'no')
('Identity-H', 'yes')
('WinAnsi', 'no')
('WinAnsi', 'no')
0 голосов
/ 18 декабря 2018

Вы можете собирать позиции строк для каждого нужного столбца:

with open('pdffonts.txt') as f:
    header =f.readline()
    read_data = f.read()
f.closed

header_values = header.split()

positions = {}
for name in header_values:
    positions[name] = header.index(name)
print(positions)

Это даст вам следующий пример:

{'name': 0, 'type': 37, 'encoding': 55, 'emb': 72, 'sub': 76, 'uni': 80, 'object': 84, 'ID': 91}

После этого вы можете указать диапазон подстроки для извлечения:

desired_columns = []
for line in read_data.splitlines()[1:]:
    encoding = line[positions['encoding']:positions['emb']].strip()
    uni = line[positions['uni']:positions['object']].strip()
    desired_columns.append([encoding,uni])

print(desired_columns)

результат:

[['WinAnsi', 'no'], ['WinAnsi', 'no'], ['Identity-H', 'yes'], ['WinAnsi', 'no'], ['WinAnsi', 'no']]
0 голосов
/ 18 декабря 2018

Использование GNU awk:

awk -v FIELDWIDTHS='36 1:17 1:16 1:3 1:3 1:3 1:9' '{ print $3, $6 }' file
encoding         uni
---------------- ---
WinAnsi          no
WinAnsi          no
Identity-H       yes
WinAnsi          no
WinAnsi          no

С man gawk:

FIELDWIDTHS

Разделенный пробеламисписок ширины полей.Если установлено, gawk анализирует входные данные в поля фиксированной ширины вместо использования значения переменной FS в качестве разделителя полей.Каждой ширине поля может дополнительно предшествовать разделенное двоеточиями значение, указывающее количество символов, которые следует пропустить до начала поля ...

...