Warm tip: This article is reproduced from serverfault.com, please click

awk-使用grep从文件中匹配python多行表达式字符串?

(awk - matching python multiline expression string from a file using grep?)

发布于 2020-11-30 12:50:30

请注意,这不是python问题。我有多个目录(大约500个目录,称为模块),__manifest__.py每个目录都包含一个文件。该文件被视为模块的元数据。该文件如下所示:

{
    'name': 'Associations Management',
    'version': '0.1',
    'category': 'Marketing',
    'depends': [
        'base_setup', 
        'membership',
        'event'
    ],
    'data': ['views/views.xml'],
    'demo': [],
    'installable': True,
    'auto_install': False,
}

我想匹配并提取(仅使用Linux Shell)一种模式,该模式可能如下:

'depends': ['base', 'web],
// or multi-line as
"depends": [
    'base',
    'web',
]

我真的对使用Linux命令(例如grepsedawk&)提取此类信息感兴趣,我对使用python解释器评估每个文件不感兴趣。所以我用下面的Linux命令

find . -iname __manifest__.py | xargs -I{} grep -H -E "('|\")depends('|\")(.?|\n)*\]\s*," {}

但是我的正则表达式没有为我提供多行选择。我也担心匹配更多不需要的行,如下所示:

'depends': [
        'base_setup', 
        'membership',
        'event'
    ],
    'data': ['views/views.xml'],

谢谢你

Questioner
mohamed ahmed
Viewed
0
Sundeep 2020-11-30 21:23:39

GNU grep

$ grep -zoE "'depends'"':\s*\[[^][]+]' ip.txt | tr '\0' '\n'
'depends': [
        'base_setup', 
        'membership',
        'event'
    ]
  • -z选项将导致grep使用ASCII NUL字符作为分隔符。因此,假设你的输入文件没有此字符,则实际上这意味着输入被读取为单个字符串
  • -o 只得到匹配的部分
  • "'depends'"':\s*\[[^][]+]'将匹配,'depends':后跟可选的空格,后跟[字符,然后是一个或多个非[]字符,然后是]
    • 这意味着任何嵌套[]序列都不适合此解决方案
  • tr '\0' '\n'将NUL字符转换为换行符,这-z也意味着将NUL用作输出中的分隔符

使用ripgrep

$ rg -oUN "'depends'"':\s*\[[^\]\[]+]' ip.txt
'depends': [
        'base_setup', 
        'membership',
        'event'
    ]

优点是,这不依赖于NUL字符,也不必一次读取整个输入。-U是多行匹配选项,并-N关闭行号前缀(终端输出默认情况下为开)。此外,双方GNU greprg支持递归搜索。


如果你要匹配的数据始终是整行,而'depends': [在一行中,则也可以使用awk请参见如何在两种模式(包括sed,AWK或Perl)之间打印线条?进行解释。

$ awk '/\047depends\047:[[:blank:]]*\[/{f=1} f; /]/{f=0}' ip.txt
    'depends': [
        'base_setup', 
        'membership',
        'event'
    ],