【问题标题】:Bash use match regex with lookbehind pattern on stringBash 在字符串上使用匹配正则表达式和后向模式
【发布时间】:2021-04-27 13:15:04
【问题描述】:

bash --version

GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin19)

说明:

我想从这个字符串字典中提取WorkingDir键值:

config="""
"TerraformCommand": "terragrunt-info",
  "WorkingDir": "usr/terraform-modules/terraform-aws-codebuild/examples/.terragrunt-cache/xh9X2WgTwVjjRHiPBjKUl0Lr86w/SGN8gG45haGoXT7IhOh9_iuKkbc"
}
"""

在这种情况下,预期的输出是:

"usr/terraform-modules/terraform-aws-codebuild/examples/.terragrunt-cache/xh9X2WgTwVjjRHiPBjKUl0Lr86w/SGN8gG45haGoXT7IhOh9_iuKkbc"

尝试:

到目前为止,我已经尝试使用不同的方法,使用这种积极的后向/前瞻模式:'(?<=("WorkingDir":\s")).+(?=")' 1.

echo `expr "$config" : '(?<=("WorkingDir":\s")).+(?=")'`

输出:0

2.

pat='(?<=("WorkingDir":\s")).+(?=")'
[[ $config =~ $pat ]]
echo "${BASH_REMATCH[0]}"
echo "${BASH_REMATCH[1]}"

输出:


echo $config | grep -o '(?<=("WorkingDir":\s")).+(?=")'

输出:

【问题讨论】:

  • @oguzismail, ...假设 OP 在 GNU 平台上,其中编译了可选的 libpcre 支持。这不仅是理论上的可能性 - 没有 libpcre 的 GNU grep 是我的经常在野外看到。
  • @Marshallm, ...另外,您的代码看起来像是 YAML 或 JSON;使用真正的语法感知解析器解析它们将比任何基于 PCRE 的黑客更可靠,即使您确实具有完整的前瞻/后视/等。
  • ...有关为什么历史上定义的正则表达式方法(可以编译为有限状态机)比新的“现代”即席正则表达式语法更好的学术讨论,请参阅swtch.com/~rsc/regexp/regexp1.html。简短形式:1970 年代的方式保证非常快速执行; “现代”方法具有令人讨厌的性能极端情况,并且可能非常缓慢。再说一遍:最好不要依赖那些花哨的新“现代”功能。
  • 顺便说一句,echo $config 有问题;总是echo "$config",带引号。见I just assigned a variable, but echo $variable shows something else!——如果你的变量包含一个被空格包围的*,你不希望它被当前目录中的文件列表替换。
  • @Marshallm 使用 POSIX DFA 还是非 POSIX NFA 确实是基于选项的。请忽略这些讨论。始终以最适合您的方式使用工作。如果您只有 GNU grep,echo $config | grep -oP '"WorkingDir":\s*"\K[^"]+' 将为您工作,但您使用的是 Mac,因此您需要先安装 GNU grep(或 pcregrep)。 sed 也可以在这里使用。但是 Bash 与捕获组匹配也很好。但是,应该使用专用工具解析 JSON,例如 jq。正则表达式是这里的最后手段。

标签: regex bash grep


【解决方案1】:

正如 cmets 中所指出的,expr 仅使用“基本”(也称为“过时”)正则表达式,而 bash 的 =~ 运算符使用的正则表达式引擎不支持前瞻或后瞻(或 @ 987654323@ 空格的简写)。但是您不需要环顾四周,只需匹配 everything 并使用捕获组来挑选您想要的部分(并将模式存储在变量中以避免可能的解析不一致):

WorkingDirPattern='\"WorkingDir":[[:space:]]\"([^"]+)\"'
if [[ "$config" =~ $WorkingDirPattern ]]; then
    WorkingDir="${BASH_REMATCH[1]}"    # get the contents of the first capture group
    echo "WorkingDir is $WorkingDir"
else
    echo "No WorkingDir found" >&2
fi

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-10-22
    • 1970-01-01
    • 2016-05-29
    • 2022-01-03
    • 1970-01-01
    • 2015-11-14
    • 1970-01-01
    相关资源
    最近更新 更多