Python多行模式匹配

时间:2014-09-19 20:48:59

标签: python subprocess pcregrep

我试图通过python使用shell命令匹配多行模式。

我可以使用shell命令进行匹配,但是我无法通过Python subprocess.call或os.system模块传递此命令。

我的文件看起来像这样:

(CELL
  (CELLTYPE "NAND_2X1")
  (INSTANCE U2)
  (DELAY
    (ABSOLUTE
    (IOPATH A1 ZN (0.02700::0.02700) (0.01012::0.01012))
    (IOPATH A2 ZN (0.02944::0.02944) (0.00930::0.00930))
    )
  )
)

不,我想提取这个:

  (INSTANCE U2)
  (DELAY
    (ABSOLUTE
    (IOPATH A1 ZN (0.02700::0.02700) (0.01012::0.01012))
    (IOPATH A2 ZN (0.02944::0.02944) (0.00930::0.00930))
    )
  )

使用此正则表达式:

pcregrep -M -n 'INSTANCE U2((?!^\)).*\n)+' sdf/c1_syn_buf2.sdf

其中U2是搜索字符串,sdf / c1_syn_buf2.sdf是文件名

在Python中,我已经定义了一个函数,我将传递搜索字符串和文件名,因为我必须多次执行此操作。

我无法使用以下内容成功执行此命令:

>>>b = subprocess.call(['pcregrep','-M','-n','INSTANCE '+arg, '\)((?!^\).*\n)+ '+file ])
pcregrep: Failed to open \)((?!^\).*
)+ /home/sanjay/thesis/code/sdf/c7552_syn_buf0.sdf: No such file or directory

当我实际输入参数(在本例中为U2)名称和文件名时,我能够获得所需的输出。

修改 如果pcregrep不够友好,这里是awk命令:

awk '/INSTANCE U2/,/^)\n?/' sdf/c1_syn_buf2.sdf

返回相同的内容。

有人可以帮帮我吗?

3 个答案:

答案 0 :(得分:1)

只是查看原始命令行,并将调用格式化为每行一个arg,不应该是这样吗?

b = subprocess.call(
['pcregrep',
    '-M',
    '-n',
    'INSTANCE {}\)((?!^\)).*\n)+ '.format(arg),
    file ])

我对括号和反斜杠不太确定。这些在正则表达式中总是有点棘手。您可能需要稍微调整它们以获得您想要的内容(在python文档中查看r''正则表达式字符串类型)

答案 1 :(得分:1)

看起来我需要使用格式说明符%s

我使用时可以使用:

b = subprocess.check_output("pcregrep -M -n 'INSTANCE '%s'((?!^\)).*\n)+' {} ".format(file) %arg,shell=True)

有了这个,我得到了变量b

的完全匹配

我使用%s传递参数,使用{} .format方法

传递文件名

答案 2 :(得分:1)

运行shell命令:

$ pcregrep -M -n 'INSTANCE U2((?!^\)).*\n)+' sdf/c1_syn_buf2.sdf
Python中的

from subprocess import check_output as qx

output = qx(['pcregrep', '-M', '-n', r'INSTANCE {}((?!^\)).*\n)+'.format(arg),
             path_to_sdf])
  • 使用r''字面值或双倍所有反斜杠
  • 将每个shell参数作为单独的列表项
  • 传递

此外,您不需要pcregrep,您可以在Python中搜索文件:

import re
from mmap import ACCESS_READ, mmap

with open(path_to_sdf) as f, mmap(f.fileno(), 0, access=ACCESS_READ) as s:
    # arg = re.escape(arg) # call it if you want to match arg verbatim
    output = re.findall(r'INSTANCE {}((?!^\)).*\n)+'.format(arg).encode(), s,
                        flags=re.DOTALL | re.MULTILINE)

mmap用于容纳不适合内存的文件。它也可能在Windows上运行得更快。