python - 在某些条目充当后续条目的标题的列表中循环的最 Pythonic 方式是什么?
问题描述
作为记录 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()
解决方案
感谢@fsimonjetz 的提示。如果你想让它成为一个答案,我可以接受,但在评论中添加我在你的建议中实施的内容,这样对于那些匆忙寻找答案的人来说,这不再是没有答案的。
解决方案是利用所有“标题行”开头的幸运事实,Project:
并将整个 sysout 字符串分解为每个标题子字符串.split('Project: ')
。对于每个子字符串,进一步的解析是通常的正则表达式.splitlines()
、、&[1:]
列表切片。
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()
推荐阅读
- python - Pytorch:通过训练有素的 CNN 运行测试图像期间的大小不匹配
- android - 在android中搜索时如何设置延迟时间
- java - 将输入输入部分(scanf)添加到java函数中的最佳方法返回数组
- c++ - 我如何从主调用插入?
- .net-core - .net core 2.1 验证状态:无效
- reactjs - 'Fragment' 已定义但从未在使用 ESLint 的 React 应用程序中使用 no-unused-vars 警告
- xamarin - Xamarin 表单:AbsoluteLayout
- java - Java Poem Palindrome Checker:按顺序遍历数组匹配元素
- java - 如何自动确定 RecyclerView 网格的项目适合计数
- python - 异步初始化时将参数传递给python类