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