从pdffonts的命令输出中只获取第三列和第六列



我正在使用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

现在,我只想在上面的输出中获得"encoding"one_answers"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

您可以收集每个所需列的字符串位置:

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)

这将为您提供以下dictinary示例:

{'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']]

使用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:

FIELDVIDTHS

以空格分隔的字段宽度列表。设置后,gawk将输入解析为固定宽度的字段,而不是使用FS变量的值作为字段分隔符。每个字段宽度前面可以有一个冒号分隔的值,指定字段开始前要跳过的字符数。。。

您可以使用列名下面的短划线来确定在哪里划线。

方便的是,我们可以在第二行中找到连续的"------",并在每个短划线序列的开头和结尾剪切列(从" -"开始,到"- "结束(。

我编写了函数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')

同样使用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 "$enctt$F[-3]" ' some.pdf
encoding                uni
----------------                ---
WinAnsi         no
WinAnsi         no
Identity-H              yes
WinAnsi         no
WinAnsi         no
> 

相关内容

  • 没有找到相关文章

最新更新