【问题标题】:Regexp to match either string, either int正则表达式匹配任一字符串,要么 int
【发布时间】:2021-02-16 01:04:06
【问题描述】:

假设我们有以下字符串:

$a = 'a == 1';
$b = 'b == "1"';
$c = "c == '1'";
$d = "d == 'd'";

我想使用正则表达式匹配引号中的数字/元素,在以下情况下:

  • 如果我们没有(单引号或双引号),我们只能匹配(正)数字和数字
  • 如果我们有引号,我们匹配所有引号。

其实我的正则表达式是

((?<guillemet>"|\')(?<valeur>.*?)(\k<guillemet>)|(?<valeur_numerique>\d+)) 

所以我在结果数组中得到三个键:'guillemet'、'valeur_numerique' 和 'valeur'。例如$a,我得到

array (
  0 => '1',
  'guillemet' => '',
  1 => '',
  'valeur' => '',
  2 => '',
  3 => '',
  'valeur_numerique' => '1',
  4 => '1',
)

是否可以简化正则表达式,以便直接拥有valeur,而无需关注引号?即对于$a,得到

array (
  0 => '1',
  1 => '',
  'valeur' => '1',
  2 => '',
  3 => '',
  4 => '1',
)

无需自己编写任何类型的过滤。

【问题讨论】:

  • 无法理解您显示的输入参数与您在问题结束时实际询问的内容之间的联系
  • 这在很大程度上取决于您的输入。如果字符串是独立的并且是这样的,你可以试试this regex,比如(?&lt;guillemet&gt;["\'])(?&lt;valeur&gt;(?:(?!\k&lt;guillemet&gt;)\D)*)(\k&lt;guillemet&gt;)|(?&lt;valeur_numerique&gt;\d+)
  • @AlivetoDie 我已经更改了我的文字,以便更清楚。
  • @WiktorStribiżew 谢谢。我看了你的正则表达式。因为,在我的示例中,$a、$b、$c 等是要测试的值的一部分。我需要测试 $a, $b, $c (preg_match('myregepx', $a)。使用您的正则表达式,我的数组中仍然有三个项目。
  • 如果您定义了三个组,您将始终将它们包含在输出中。您可以简单地使用array_filter 删除空的。

标签: php regex


【解决方案1】:

不要试图将其全部压缩成一个(子)模式。更容易定义替代方案。我通常会单独取消引用该值,但可以使用 J (PCRE2_DUPNAMES) 修饰符。它允许重复的组名。

$pattern = '(
  (?<literal>                
    (?:"(?<value>[^"]*)")|    # double quoted value
    (?:\'(?<value>[^\']*)\')| # single quoted value
    (?:(?<value>[+-]?\d+))    # signed integer
  )
)xJ';
    
$examples = [
    'a == 1', 'b == "1"', "c == '1'", "d == 'd'", "some == other"
];

foreach ($examples as $example) {
    echo $example, "\n";
    if (preg_match($pattern, $example, $match)) {
        echo json_encode(
            array_filter($match, fn($key) => is_string($key), ARRAY_FILTER_USE_KEY),
            JSON_PRETTY_PRINT
        ), "\n";
    } else {
        echo "NO_MATCH\n";
    }
}

输出:

a == 1
{
    "literal": "1",
    "value": "1"
}
b == "1"
{
    "literal": "\"1\"",
    "value": "1"
}
c == '1'
{
    "literal": "'1'",
    "value": "1"
}
d == 'd'
{
    "literal": "'d'",
    "value": "d"
}
some == other
NO_MATCH

【讨论】:

  • 谢谢。我提出问题的主要原因是避免过滤我的输出a后验。所以你的答案不明白,因为它需要我过滤引号。
  • 更新了答案以捕获不带引号的值。
  • 谢谢!很好。
猜你喜欢
  • 2013-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-05
  • 2013-12-25
  • 1970-01-01
相关资源
最近更新 更多