请问正则表达式如何匹配某些标点符号必须成对地出现?

jxfinest 2019-09-30 08:57:09
《》〈〉(){}【】『』,出现的标点种类不确定,但出现即必须成对。

《童年》练习题(含答案)_『百度文库』 成立
《童年练习题(含答案)_百度文库 不成立
《童年》练习题(含答案_百度文库 不成立
《童年》练习题【含答案】_(百度文库 不成立
《童年》练习题【含答案】_(百度文库) 成立
...全文
380 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
github_36000833 2019-10-07
  • 打赏
  • 举报
回复
使用多个平衡组,是可以做到每组平衡。
(?x) # 允许空白和注释
^
(
  [^《》〈〉(){}【】『』]   # 不包含特定符号的
|
 《(?<dab>) | 》(?<-dab>)  # 看到《》,相应增减dab(Double Angle Bracket)平衡组
|
 〈(?<ab>) | 〉(?<-ab>)
|
  \((?<p>) | \)(?<-p>)
|
 {(?<cb>) | }(?<-cb>)
|
 【(?<sqb>) | 】(?<-sqb>) 
|
  『(?<cnb>) | 』(?<-cnb>)
)*
(?(dab)(?!))  #检查Double Angle Bracket平衡组余量不为零
(?(ab)(?!))   #检查Angle Bracket平衡组
(?(p)(?!))    #检查Parenthesis平衡组
(?(cb)(?!))   #检查CurlyBrace平衡组
(?(sqb)(?!))  #检查SquareBracket平衡组
(?(cnb)(?!))  #检查CornerBracket平衡组
$
这样可以做到每组平衡。比如 《童年【练习题含答案】》 不过,交错匹配还待改进,即还不能判断如下交错配对(如果需要严格配对的话): 《童年【练习题含答案》】 用代码就容易控制了:
class Program
{
    static void Main(string[] args)
    {
        var b1 = IsBalanced("《童年》练习题【含答案】_(百度文库) 成立");  // true
        var b2 = IsBalanced("《《《《《《童年》【含答案】》》(百度文库)》》》"); // true
        var b3 = IsBalanced("《童年 文库』");  // false
        var b4 = IsBalanced("《童年【练习题含答案》】"); // false;
    }

    static bool IsBalanced(string input)
    {
        const string pairs = "《》〈〉(){}【】『』";
        var stack = new Stack<char>();
        foreach(char c in input)
        {
            int i = pairs.IndexOf(c);
            if (i == -1)
            {
                continue;  // 非符号,跳过
            }
            if (i % 2 == 0)
            {
                stack.Push(c); // 偶数为符号开启,入栈
            }
            else // 奇数为符号结束,检查堆栈顶必须是配对的‘符号开始’
            {
                if (stack.Count == 0 || stack.Pop() != pairs[i - 1])
                {
                    return false;
                }
            }
        }
        return stack.Count == 0; // 所有配对必须完成
    }
}
jxfinest 2019-10-06
  • 打赏
  • 举报
回复
经验证,确实存在 github_36000833 所述BUG
jxfinest 2019-10-03
  • 打赏
  • 举报
回复
引用 5 楼 github_36000833 的回复:
[quote=引用 3 楼 jxfinest 的回复:] ... 根据楼上提示的平衡组,自已摸索着搞定,加了一些条件,不匹配空格换行,。、;等 ...
鼓励并赞一个。 如果你要符号匹配,可能要用多个平衡组。只用总量匹配,不能解决如下的输入:
《童年 文库』
用正则的目的,是使开发更加容易。如果发现正则更麻烦,就是时候考虑其他做法。[/quote] 你提到的:《童年 文库』的情况 我记得我是考虑过这种情况的呀,但是现在国庆回家在车上没有电脑验证,我这里是 (”|》|〉|)|\)|】|』|}) 而非 [”》〉)\)】』}]
github_36000833 2019-10-03
  • 打赏
  • 举报
回复
引用 3 楼 jxfinest 的回复:
...
根据楼上提示的平衡组,自已摸索着搞定,加了一些条件,不匹配空格换行,。、;等
...


鼓励并赞一个。
如果你要符号匹配,可能要用多个平衡组。只用总量匹配,不能解决如下的输入:
《童年 文库』


用正则的目的,是使开发更加容易。如果发现正则更麻烦,就是时候考虑其他做法。
jxfinest 2019-10-02
  • 打赏
  • 举报
回复
jxfinest 2019-10-02
  • 打赏
  • 举报
回复
引用 1 楼 github_36000833 的回复:
正则不是最好的选择,它需要用到平衡组,写着麻烦还不好维护。 使用代码进行状态分析,只要几行代码,还快。

static bool IsBalanced(string input)
{
    const string pairs = "《》〈〉(){}【】『』";
    var counters = new int[pairs.Length / 2];
    input
        .Select(x => pairs.IndexOf(x))
        .Where(x => x >= 0)
        .ToList()
        .ForEach(x => counters[x / 2] += ((x & 1) * 2 - 1));
    return counters.Sum() == 0;
}
根据楼上提示的平衡组,自已摸索着搞定,加了一些条件,不匹配空格换行,。、;等 [^,,、。:?;“”《》〈〉()()【】『』{}\s]*(((?'jxfinest'(“|《|〈|(|\(|【|『|{))[^,,、。:?;“”《》〈〉()()【】『』{}\s]*)+((?'-jxfinest'(”|》|〉|)|\)|】|』|}))[^,,、。:?;“”《》〈〉()()【】『』{}\s]*)+)*(?(jxfinest)(?!))
github_36000833 2019-10-02
  • 打赏
  • 举报
回复
更正(#1楼): static bool IsBalanced(string input) { ... return couters.All(x => x == 0); }
github_36000833 2019-10-01
  • 打赏
  • 举报
回复
正则不是最好的选择,它需要用到平衡组,写着麻烦还不好维护。
使用代码进行状态分析,只要几行代码,还快。

static bool IsBalanced(string input)
{
const string pairs = "《》〈〉(){}【】『』";
var counters = new int[pairs.Length / 2];
input
.Select(x => pairs.IndexOf(x))
.Where(x => x >= 0)
.ToList()
.ForEach(x => counters[x / 2] += ((x & 1) * 2 - 1));
return counters.Sum() == 0;
}
目录 本文目标 如何使用本教程 正则表达式到底是什么东西? 入门 测试正则表达式 元字符 字符转义 重复 字符类 分枝条件 反义 分组 后向引用 零宽断言 负向零宽断言 注释 贪婪与懒惰 处理选项 平衡组/递归匹配 还有些什么东西没提到 联系作者 网上的资源及本文参考文献 本文目标 30分钟内让你明白正则表达式是什么,并对它有一些基本的了解,让你可以在自己的程序或网页里使用它。 如何使用本教程 最重要的是——请给我30分钟,如果你没有使用正则表达式的经验,请不要试图在30秒内入门——除非你是超人 :) 别被下面那些复杂的表达式吓倒,只要跟着我一步一步来,你会发现正则表达式其实并没有你想像中的那么困难。当然,如果你看完了这篇教程之后,发现自己明白了很多,却又几乎什么都记不得,那也是很正常的——我认为,没接触过正则表达式的人在看完这篇教程后,能把提到过的语法记住80%以上的可能性为零。这里只是让你明白基本的原理,以后你还需要多练习,多使用,才能熟练掌握正则表达式。 除了作为入门教程之外,本文还试图成为可以在日常工作中使用的正则表达式语法参考手册。就作者本人的经历来说,这个目标还是完成得不错的——你看,我自己也没能把所有的东西记下来,不是吗? 清除格式 文本格式约定:专业术语 元字符/语法格式 正则表达式 正则表达式中的一部分(用于分析) 对其进行匹配的源字符串 对正则表达式或其中一部分的说明 隐藏边注 本文右边有一些注释,主要是用来提供一些相关信息,或者给没有程序员背景的读者解释一些基本概念,通常可以忽略。 正则表达式到底是什么东西? 字符是计算机软件处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等等。字符串是0个或更多个字符的序列。文本也就是文字,字符串。说某个字符串匹配某个正则表达式,通常是指这个字符串里有一部分(或几部分分别)能满足表达式给出的条件。 在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。 很可能你使用过Windows/Dos下用于文件查找的通配符(wildcard),也就是*和?。如果你想查找某个目录下的所有的Word文档的话,你会搜索*.doc。在这里,*会被解释成任意的字符串。和通配符类似,正则表达式也是用来进行文本匹配的工具,只不过比起通配符,它能更精确地描述你的需求——当然,代价就是更复杂——比如你可以编写一个正则表达式,用来查找所有以0开头,后面跟着2-3个数字,然后是一个连字号“-”,最后是7或8位数字的字符串(像010-12345678或0376-7654321)。

110,567

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧