【发布时间】:2021-06-17 15:16:41
【问题描述】:
作为记录 CLI 工具命令的系统输出的结果...
import subprocess
list_operations_cmd = 'cloud_cli_tool --list'
all_operations_sysout = subprocess.check_output(list_operations_cmd, shell=True)
我得到一个如下所示的字符串:
Project: foo foo foo (Environment: PRODUCTION)
ipsum dolor sit
Excepteur sint occaecat
POST aliquip ex ea
Project: foo foo foo (Environment: DEVELOPMENT)
ipsum dolor sit
Excepteur sint occaecat
POST aliquip ex ea
Project: bar (Environment: PRODUCTION)
velit esse cillum
occaecat cupidatat
我想把它变成一个看起来像这样的数据结构,以促进我的工作对我正在编写这个 Python 脚本以向系统用户公开的命令接口的参数进行输入清理。
[
{
project: "foo foo foo",
environment: "PRODUCTION",
operation: "ipsum dolor sit"
},
{
project: "foo foo foo",
environment: "PRODUCTION",
operation: "Excepteur sint occaecat"
},
{
project: "foo foo foo",
environment: "PRODUCTION",
operation: "POST aliquip ex ea"
},
{
project: "foo foo foo",
environment: "DEVELOPMENT",
operation: "ipsum dolor sit"
},
{
project: "foo foo foo",
environment: "DEVELOPMENT",
operation: "Excepteur sint occaecat"
},
{
project: "foo foo foo",
environment: "DEVELOPMENT",
operation: "POST aliquip ex ea"
},
{
project: "bar",
environment: "PRODUCTION)",
operation: "velit esse cillum"
},
{
project: "bar",
environment: "PRODUCTION)",
operation: "occaecat cupidatat"
}
]
如您所见,项目/环境的变化可以通过不带缩进的换行来检测;可以通过换行符后跟两个空格来检测记录的更改。项目/环境行充当以下行的“标题”,直到检测到新的“项目/环境行”。
我知道我可以只 .splitlines() 整个事情并开始一次循环一行,缓存内容并 if-then-elsing ......但感觉可能有一种比 Pythonic 更:
proj_env_pattern = r'^Project: (.*) \(Environment: (.*)\)$'
all_operations_list = all_operations_sysout.splitlines()
for line in all_operations_list[:20]:
is_header = False
if not line.startswith(' '):
is_header = True
project = re.search(proj_env_pattern, line, re.IGNORECASE).group(1)
print project
# TO DO: code...
# TO: code...
Linux 上的 Python 2.7.5;无法安装任何新模块。
更新:
感谢@fsimonjetz 的提示。如果你想让它成为答案,我可以接受并关闭。
代码现在比我做的要整洁得多:
import re
import subprocess
def get_all_operations():
list_operations_cmd = 'cloud_cli_tool --list'
proj_env_pattern = r'^(.*) \(Environment: (.*)\)$'
all_operations_list = []
all_projects = subprocess.check_output(list_operations_cmd, shell=True).split('Project: ')
for project in all_projects[1:]:
project_lines = project.splitlines()
project_search = re.search(proj_env_pattern, project_lines[0])
for line in project_lines[1:]:
all_operations_list.append({'project': project_search.group(1), 'environment': project_search.group(2), 'operation': line.lstrip()})
return all_operations_list
print get_all_operations()
【问题讨论】:
-
到目前为止您尝试过什么?什么不工作? @k..
-
好吧,我知道我可以
.splitlines()并一次循环遍历它,并执行各种手动 if-else 操作以查找从一行到下一行的变化,但我不太擅长“更聪明”的做事方式,只是好奇是否有人有任何“更聪明”、“更 Pythonic”的想法。更新的问题。 -
那就写一些吧。不要担心你的代码有多 Pythonic,直到你有一些可以工作的东西。
-
如果输入是正则,你甚至不需要正则表达式。可以先
.split('Project:')整个字符串将所有片段放入一个列表中,然后循环它以提取其他部分。 -
@fsimonjetz -- 聪明 -- 谢谢你,这是我知道别人会建议的技巧!!!想让它成为答案吗?
标签: python python-2.7 text-parsing