Python多行模式匹配

Python多行模式匹配,python,subprocess,pcregrep,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.0294

我试图通过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中,我定义了一个函数,我将向该函数传递搜索字符串和文件名,因为我必须多次执行此操作

我无法使用以下命令作为shell命令成功执行此命令:

>>>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
返回相同的值


有人能帮我吗?

只需查看原始命令行,并将调用的格式设置为每行一个参数,是否应该是这样

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

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

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

当我使用:

b = subprocess.check_output("pcregrep -M -n 'INSTANCE '%s'((?!^\)).*\n)+' {} ".format(file) %arg,shell=True)
这样,我就得到了变量
b


我使用%s传递参数,使用
{}.format
方法传递文件名来运行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])
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)
  • 使用
    r'
    literal或将所有反斜杠加倍
  • 将每个shell参数作为单独的列表项传递
此外,您不需要
pcregrep
,您可以用Python搜索该文件:

from subprocess import check_output as qx

output = qx(['pcregrep', '-M', '-n', r'INSTANCE {}((?!^\)).*\n)+'.format(arg),
             path_to_sdf])
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上也可能运行得更快。

我想您只是有一个打字错误:.*\n)+'+文件它可能应该是.*\n)+',用逗号而不是逗号的文件plus@rkh这不是打字错误,括号中的内容基本上是说
(.*\n)+
,我添加了
(?!\))
表示只有在遇到以
开头的行时才需要进行匹配。
分隔arg from')的逗号也应该是+,我认为,因此列表中的元素是子流程callI的单个参数,我没有得到这个参数,我想在搜索字符串中输入
arg
。格式行将在搜索字符串中输入arg。如果arg设置为“Hello”,那么“INSTANCE{}”(?!^)。*\n)+。format(arg)等于“INSTANCE Hello”(?!^)。*\n)+”(加上或减去一些反斜杠)嗯……我实际上刚刚尝试过,现在pcregremp报告错误:
>b=subprocess.call(['pcregremp','-M','-n','INSTANCE{}\(?!^\).\n')。format(arg),file])pcregrep:命令行正则表达式中偏移量为25的错误:丢失)
我希望有一个简单的backtick或exec方法用于类似perl的Python!看看你原来的正则表达式,我想我在中间忘了一个额外的“”。我刚刚编辑过。希望反斜杠是正确的…您应该使用
%
.format
字符串格式。同时使用这两个命令看起来很难看。@Sebastian我对python相当陌生,因此使用的是Unix命令。.感谢mmap方法,它工作得非常好!感谢对qx的类似perl的方法