强制 Bash 使用 Perl RegEx 引擎

Fad*_*ass 13 bash perl regular-expression

您可能已经知道,Bash RegEx 引擎不支持现代 RegEx 引擎支持的许多功能(反向引用、环视断言等)。以下是我刚刚创建的一个简单的 Bash 脚本,试图解释我的最终目标是什么:

#!/bin/bash

# Make sure exactly two arguments are passed.
if [ $# -lt 2 ]
then
    echo "Usage: match [string] [pattern]"
    return
fi

variable=${1}
pattern=${2}

if [[ ${variable} =~ ${pattern} ]]
then
    echo "true"
else
    echo "false"
fi
Run Code Online (Sandbox Code Playgroud)

因此,例如,类似以下命令的内容将返回 false:

. match.sh "catfish" "(?=catfish)fish"
Run Code Online (Sandbox Code Playgroud)

而完全相同的表达式在 Perl 或 JavaScript 正则表达式测试器中使用时会找到匹配项。

反向引用(例如 (expr1)(expr2)[ ]\1\2)也不会匹配。

我得出的结论是,只有强制 bash 使用与 Perl 兼容的 RegEx 引擎才能解决我的问题。这是可行的吗?如果是这样,我将如何执行该程序?

slm*_*slm 17

Bash 目前不支持您执行此操作的方法。剩下的选项如下:

  1. 使用 Perl
  2. grep [-P|--perl-regexp]
  3. 使用 Bash 功能对其进行编码

我想我会选择 #2 并尝试使用grep来获得我想要的功能。对于反向引用,您可以执行以下操作grep

$ echo 'BEGIN `helloworld` END' | grep -oP '(?<=BEGIN `).*(?=` END)'
helloworld
Run Code Online (Sandbox Code Playgroud)
-o, --only-matching       show only the part of a line matching PATTERN
-P, --perl-regexp         PATTERN is a Perl regular expression
Run Code Online (Sandbox Code Playgroud)
(?=pattern)
    is a positive look-ahead assertion
(?!pattern)
    is a negative look-ahead assertion
(?<=pattern)
    is a positive look-behind assertion
(?<!pattern)
    is a negative look-behind assertion 
Run Code Online (Sandbox Code Playgroud)

参考

  • 对于后代,只有 GNU grep 包含 `-P` 选项,并且它不是通用的。FreeBSD 的 grep 基于 GNU,但文档声明“FreeBSD 不支持此选项”。在 OSX 中,grep 也基于 GNU,但在手册页中甚至没有提到 `-P` 选项。而在 grep 不是 GNU 的其他 unix 系统上,您根本不可能在任何地方看到 `-P`。如果您认为可移植性将来对您有用的可能性很小,我建议您避免使用此类特定于操作系统的选项。 (3认同)
  • 应该注意的是,只要设置了“REMATCH_PCRE”选项,zsh 就会完全按照 OP 的要求执行。 (2认同)