2

我正在尝试通过 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

返回相同。

有人可以帮我吗?

4

3 回答 3

1

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

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

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

于 2014-09-19T21:00:22.220 回答
1

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

它在我使用时有效:

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

有了这个,我得到了变量的完全匹配b

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

于 2014-09-19T21:25:20.307 回答
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 上运行得更快。

于 2014-09-20T12:28:03.753 回答