Bash:grep 包括换行符

Bash:grep 包括换行符

尝试对两个括号之间的所有内容进行正则表达式处理{ }。类似问题 正则表达式匹配任何字符,包括换行符 - Vi & Vim,但我不明白提供的解决方案。


使用:

nft list table inet filter

返回此:

table inet filter {
    set ipaddr {
        type ipv4_addr
        flags timeout
        elements = { 192.168.1.102, 192.168.1.119,
                 192.168.1.133, 192.168.1.134 }
    }
}

我想使用正则表达式来获取元素内的所有内容,例如:

192.168.1.102,192.168.1.119,192.168.1.133,192.168.1.134 

我以为我可以使用grep,但只要能用就很好了。

答案1

链接中的信息特定于 vi/vim 正则表达式,并不直接适用于 grep。

grep 中的等效项可能是使用 perl 兼容正则表达式 (PCRE),其s修饰符告诉正则表达式引擎在“任何字符”集中包含换行符.(通常.意味着任何字符除了新队)。

例如pcregrep使用Multiline 标志:

$ pcregrep -Mo '(?s)elements = {.*?}' yourexample
elements = { 192.168.1.102, 192.168.1.119,
                 192.168.1.133, 192.168.1.134 }

您可以在常规 GNU grep 中强制执行类似的操作,方法是使用标志-z作为代理-M

grep -zPo '(?s)elements = {.*?}'

如果您也想格式化匹配的文本,我会切换到 perl 适当的 ex。

$ perl -00nE 'say $1 =~ s/\n\s*/ /r if m/elements = {(.*?)}/s' yourdata
 192.168.1.102, 192.168.1.119, 192.168.1.133, 192.168.1.134

答案2

另一个解决方案是:

nft list table inet filter | sed -zne 's/^.*elements = { //; s/ }.*$//; s/[ \n]\+/ /gp'

在这里我们使用:

  • -z将整个输入视为一行的选项。
  • -n抑制模式空间自动打印的选项。

在脚本部分:

  • 第一个脚本(s/^.*elements = { //;)删除从开头到elements = {输入的字符串的第一部分。
  • 第二个脚本(s/ }.*$//;)删除从 开始}直到输入结束的其余部分。
  • 第三个脚本(s/[ \n]\+/ /gp)将任何多个空格(换行符和空格符)g全局替换为单个空格字符并p打印结果。

答案3

这是一个sed解决方案(感谢@FedonKadifeli 关于缩短我的初始命令的建议):

nft list table inet filter | sed -zn 's/.*elements = { \([0-9,\. \n]*\) }.*/\1/; s/\n//; s/  \+/ /p'

我们将输出通过管道传输nft list table inet filter到一系列sed命令:

  • s/.*elements = { \([0-9,\. \n]*\) }.*/\1/选择elements括号之间的任何内容。
  • s/\n//删除选择中的所有换行符。
  • s/ \+/ /p用一个空格替换多个空格。

man sed

-n, --quiet, --silent

          suppress automatic printing of pattern space

-z, --null-data

          separate lines by NUL characters

输出为:

192.168.1.102, 192.168.1.119, 192.168.1.133, 192.168.1.134

答案4

您可以使用 bash 正则表达式语句。

$ [[ $(nft list table inet filter) =~ \
  elements[\ =]+\{([^}]*) ]] && echo "${BASH_REMATCH[1]//[[:space:]]/}"

相关内容