【问题标题】:How do I pass a regex to pdfgrep using the python subprocess module?如何使用 python 子进程模块将正则表达式传递给 pdfgrep?
【发布时间】:2017-06-21 13:06:35
【问题描述】:

我想使用 Python 的 subprocess 模块将正则表达式传递给 pdfgrep。代码执行没有错误,但 pdfgrep 没有正确接收参数。测试 pdf 在 cwd 中,包含字符串“Mary Jane”。这是我的代码(Python 3.6):

import subprocess
filtered = ['[A-Z].+Jane'] # the list of regexes is shortened to one string, to keep the example simple.
for regex in filtered: 
    arg = 'pdfgrep -PrH ' + f"{regex}"
    process_match = subprocess.run(arg, stdout=subprocess.PIPE, shell=True)

预期结果是process_match 将包含一个包含匹配项的CompletedProcess() 对象。

但相反,它返回以下内容:

CompletedProcess(args="pdfgrep -PrH '[A-Z].+Jane'", returncode=127, stdout=b'')

在命令行中,调用相同的pdfgrep 命令会找到匹配的pdf。我可以使用如下代码在 Ruby 中相当简单地完成这项任务:

process_match = %x[pdfgrep -PrH "#{regex}"]

我是 python 新手。尝试将正则表达式传递给外部命令时出现什么问题?

【问题讨论】:

  • 我不确定这是否是我遗漏的语法,但您是否在第一个代码示例中,-PrH 之后和/或{regex} 之前省略了空格?另外,除了pdfgrep 之外的其他程序是否也会发生这种情况? (例如,假设您在一个存在该程序的类 UNIX 系统上,您可以使用 /bin/echo 执行此操作吗?)
  • @DavidZ 关于缺少空格的说法是对的:应该是 'pdfgrep -PrH ' 但这仍然不会导致预期的结果。使用'/bin/echo ' 确实会产生预期的行为,也许这与 pdfgrep 本身有关?
  • 您的评论告诉我,我应该指定 pdfgrep 的完整路径。请参阅我对自己问题的回答。

标签: python regex python-3.x subprocess


【解决方案1】:

subprocess.run 需要一个参数列表(不是字符串),例如

arg = ['pdfgrep',  '-PrH',  f"{regex}"]

而不是arg = 'pdfgrep -PrH' + f"{regex}"

编辑:

您在使用shell=True 时应该使用字符串的评论是正确的,但正如python 子流程文档中所讨论的那样,这可能会带来安全隐患,而且很少有必要,所以最好养成这个习惯不使用外壳。

【讨论】:

  • 我知道将参数作为列表而不是字符串传递。但我认为shell=True 我需要一个字符串。在任何情况下,尝试像这样的代码for regex in filtered: arg = ['pdfgrep', '-PrH', f"{regex}"] process_match = subprocess.run(arg, stdout=subprocess.PIPE, shell=True) 仍然在 process_match CompletedProcess(args=['pdfgrep', '-PrH', '[A-Z].+Jane'], returncode=127, stdout=b'') 中给我这个值所以 pdfgrep 似乎仍然没有正确获取正则表达式。
  • 你是对的。但我还需要指定 pdfgrep 的完整路径。我已将您的建议纳入我自己的答案。谢谢。
【解决方案2】:

以下代码按预期工作:

for regex in filtered:
    arg = ['/usr/local/bin/pdfgrep',  '-PrH',  f"{regex}"]
    process_match = subprocess.run(arg, stdout=subprocess.PIPE)

我的原始代码(至少)有两个问题。首先,我需要将命令作为列表传递给subprocess.run,但要使其正常工作,我需要指定 pdfgrep 的完整路径。

【讨论】:

  • 这让我很困惑(也许你的问题没有立即得到答案),因为 /usr/local/bin 通常在 PATH 环境变量中,大多数 Python 实现都会搜索传递给 Python 解释器的路径。出于某种原因,您的路径是否受限?
  • @Patrick 我会这么认为,但我发现/usr/local/bin 在路径中实际上并不普遍。相当多的配置默认会省略它。
  • @DavidZ - 当然,但 OP 声称它可以正常工作,例如手动或使用 Ruby。那么是 Python 解释器以某种方式设置为不使用路径,还是 Ruby 解释器做了一些魔术?
  • @Patrick 确实没有足够的信息可以说明。 Python确实使用从父进程继承的路径,有点;有关详细信息,请参阅this question。我不知道 Ruby 是如何做到的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-19
  • 2020-06-09
  • 2019-10-21
  • 2014-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多