【问题标题】:Get only third and sixth column from command output of pdffonts从 pdffonts 的命令输出中仅获取第三和第六列
【发布时间】:2019-05-18 16:59:30
【问题描述】:

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

【问题讨论】:

    标签: python awk sed poppler


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

      字段宽度

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

      【讨论】:

      • FIELDWIDTHS 选项仅适用于 gawk。如果我使用 awk,我会得到错误的输出。但是对于 gawk 它工作正常。谢谢。
      【解决方案3】:

      您可以使用列名下方的破折号来确定在哪里剪线。

      我们可以很方便地在第二行找到连续的"------",并在每个破折号序列的开头和结尾切割列(以" -"开头,以"- "结尾)。

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 2013-04-14
          • 2010-12-03
          • 1970-01-01
          • 2018-02-11
          • 2020-10-01
          • 1970-01-01
          • 2013-08-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多