正则表达式:要求在字符串中引号被转义

6

谢谢查看,

我在尝试为这个正则表达式问题寻找正确的搜索词时遇到了很大的困难。我需要确保字符串中的引号已经被转义,否则匹配应该失败。(大多数此类问题的搜索结果只是页面上说你需要转义引号或者如何转义引号)

有效:

This is valid
This \"is Valid
This is al\"so Valid\"

无效:

This i"s invalid
This i"s inv"alid

到目前为止,我所找到的唯一东西是:
((?:\\"|[^"])*)

这似乎与以下内容的前半部分匹配,但转义引号后面没有任何内容。

This is a \"test

再次尝试,这应该会失败:

This is a \"test of " the emergency broadcast system

非常感谢您的帮助,我希望这是可能的。


+1,有趣的问题,正则表达式似乎是正确的工具。 - Fred Foo
@JosephSilber 我实际上没有使用一种语言,这个正则表达式将进入一个用于CMS中的正则表达式字段,需要用户输入来匹配它 :) - Bung
1
不存在“不使用语言”的事情。这个CMS使用什么语言? - Joseph Silber
1
需要注意的一个陷阱是 a\\"ba\\\\"b 是无效的,但是 a\\\"ba\\\\\"b 是有效的。这是因为在前两个示例中,在引号之前有偶数个反斜杠被绑定为转义,即使它们之前有一个反斜杠,引号也没有被转义,而在后两个示例中,在引号之前有奇数个反斜杠是可以的,因为偶数个反斜杠引用了反斜杠,留下了奇数个反斜杠来转义引号。 - Jonathan Leffler
5个回答

6
在C#中,这似乎是按照您所期望的方式工作:
string pattern = "^([^\"\\\\]*(\\\\.)?)*$";

去除转义后,你会得到:
^([^"\\]*(\\.)?)*$

大致翻译为:以字符串开头,(多个不包括引号或反斜杠的字符和可选的反斜杠加任意字符)重复,以字符串结尾。

正是由于字符串的开头和结尾标记,才能强制匹配整个文本。


这对我来说一直很有效,除了一个例外:This is " valid \。但我相信很少会有以斜杠结尾的输入,所以可以让它失败。 - Bung
2
是的,它被设计成在末尾只有一个反斜杠的情况下失败。原因是,如果字符串支持使用反斜杠的转义字符,那么单个反斜杠永远不可能是有效的。 - adelphus

2

不知道你使用的是哪种语言,但我会用这种方式来做:

制作一个正则表达式,可以匹配没有反斜杠的引号,如果有反斜杠则匹配失败。

This is a \"test

并成功了

This is a \"test of " the emergency broadcast system

例如这个例子:
.*(?<!\\)".*

然后将使用负面表达式来表示结果。希望这能帮助你。

我的Java测试看起来像:

    String pat = ".*(?<!\\\\)\".*";
    String s = "This is a \\\"test";
    System.out.println(!s.matches(pat));
    s = "This is a \\\"test of \" the emergency broadcast system";
    System.out.println(!s.matches(pat));

2
您需要使用负向回顾断言。
(?<!\\)"

下面这个正则表达式会匹配所有未被单个斜杠转义的引号。

如果你对样本字符串运行这个正则表达式并找到了1个或者多个匹配,那么这个字符串就不合法。


1

你需要取出除了反斜杠和引号,或者反斜杠和下一个字符以外的所有内容。

([^\\"]|\\.)*

这样做会失败:

ab\\"c

这将会成功:

ab\\\"c

这将会成功:

ab\"c

1

你要找的正则表达式是:

/^(?:[^"]*(?:(?<=\\\)"|))*$/

说明:[^"]*将匹配输入,直到找到第一个"或到达输入的结尾。如果找到",则确保在(?<=\\\)"回顾后面始终紧跟着/。上述情况会递归重复,直到到达输入的结尾。

测试:考虑以下PHP代码进行测试:

$arr=array('This is valid',
'This \"is Valid',
'This is al\"so Valid\"',
'This i"s invalid',
'This i"s inv"alid',
'This is a \"test',
'This is a \"test of " the emergency broadcast system - invalid');
foreach ($arr as $a) {
   echo "$a => ";
   if (preg_match('/^(?:[^"]*(?:(?<=\\\)"|))*$/', $a, $m))
      echo "matched [$m[0]]\n";
   else
      echo "didn't match\n";
}

输出:

This is valid => matched [This is valid]
This \"is Valid => matched [This \"is Valid]
This is al\"so Valid\" => matched [This is al\"so Valid\"]
This i"s invalid => didn't match
This i"s inv"alid => didn't match
This is a \"test => matched [This is a \"test]
This is a \"test of " the emergency broadcast system - invalid => didn't match

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接