Python使用os或subprocess执行grep命令失效的解决方案
Python调用grep命令异常解决方案
问题背景
需要在Python脚本中执行如下grep命令,提取目标匹配行后的内容:grep -A5000 -m1 -e 'dog 123 4335' animals.txt
测试用animals.txt文件内容:
cat 13123 23424 deer 2131 213132 bear 2313 21313 dog 123 4335 cat 13123 23424 deer 2131 213132 bear 2313 21313
命令预期输出为匹配行之后的所有内容:
cat 13123 23424 deer 2131 213132 bear 2313 21313
该命令直接在Unix终端执行可正常返回结果,但通过Python的
os.system、subprocess直接调用时经常出现执行失败、无输出的问题。
失败常见原因
- 调用
subprocess时未开启shell=True,却把完整命令字符串作为单个参数传入,系统会把整段字符串识别为可执行程序名,触发文件不存在错误 - 用列表形式传参时,给匹配关键词额外加了shell层面的单引号,导致grep实际匹配的内容是带单引号的字符串,和文件内容不匹配,返回空结果
- 未配置输出捕获参数,命令执行后结果直接打印到终端,变量拿不到返回值,误以为执行失败
可行实现(基于subprocess,推荐)
优先选择列表传参、不开启shell的写法,可避免shell注入风险,代码如下:
import subprocess # 命令拆分为列表传入,匹配关键词不需要额外加单引号 cmd = [ "grep", "-A5000", "-m1", "-e", "dog 123 4335", # 直接写匹配内容即可,不要加外层单引号 "animals.txt" ] # 执行命令,捕获标准输出 res = subprocess.run( cmd, capture_output=True, text=True, check=True # 命令执行失败时直接抛出异常,方便排查问题 ) # grep -A会把匹配行本身也输出,切片去掉第一行就是需要的后续内容 target_content = "\n".join(res.stdout.strip().splitlines()[1:]) print(target_content)
如果习惯写完整命令字符串,可以开启shell=True传入,写法如下:
import subprocess cmd = "grep -A5000 -m1 -e 'dog 123 4335' animals.txt" res = subprocess.run( cmd, shell=True, capture_output=True, text=True, check=True ) target_content = "\n".join(res.stdout.strip().splitlines()[1:]) print(target_content)
如果非要用os.system实现,需要把输出重定向到临时文件再读取,不推荐,示例写法:
import os os.system("grep -A5000 -m1 -e 'dog 123 4335' animals.txt > temp_res.txt") with open("temp_res.txt", "r") as f: lines = f.read().strip().splitlines()[1:] target_content = "\n".join(lines) print(target_content) os.remove("temp_res.txt")
内容的提问来源于stack exchange,提问作者Zenith Chokshi
相关产品推荐
相关产品推荐

