zoukankan      html  css  js  c++  java
  • 去掉[]中的英文字符

      最近在信息科技大学上传智.Net就业班的课程,中午有位信息科技大学的老师问我关于正则表达式的问题. 问题大致这么描述的:
      有一个字符串,里面是中文与英文的混排内容,中间包含几对中括号(方括号),现在有个需求,就是移除中括号中所有的英文字符,保留其他数据.
      我一看就觉得可以完成,但是随手一写发现有点问题,可能处于数学出身的原因,总想把问题尽量写得全面,我中午吃饭的时候就在考虑该怎么些比较好. 这里给出我思考这个问题的思路,看看有没有给大家一点启发.

    化归思想
      数学里面有个很重要的思想,就是“化归”思想. 什么是化归呢?简单的说,就是将复杂的问题进行归纳总结,将其变成一些简单的问题的组合,然后简单问题解决了,复杂问题也就解决了.
      有朋友就会说了:“看了数学头痛,还跟我提什么化归思想… …”
      其实不然,只是化归思想这个名字很吓人——数学思想啊,其实她很基础,因为我们天天都在用这个思想. 来一个生活中的例子,想知道一个超市的商品质量和价格好与不好,怎么考究?显然这个咱们没有办法一个个检验,但是我们看得到,可以比较. 如果这个超市总是人很多,而且消费者投诉也很少,那我们就可以下结论了,这个超市不错. 再比如说,面向对象中的一个概念,C#中继承具有传递性,这个怎么理解?其实很简单,因为继承,子类包含了父类的成员,那么一直下去,孙子类继承子类,就包含了子类成员,即是孙子类包含了父类成员,因此就有了结论,派生类都具有基类成员,自然传递性就很好理解了.

    问题化归
      那么说过了这么多和解决这个问题有什么关系呢?显然我解决这个问题使用了化归的思想. 关键是这个问题有什么难点呢?
    我们先来看一个例子:
    有一个字符串

    1 string str = "abc[你abc好]abc";

    现在要将字符串里面的“[你abc好]”中的英文字符“abc”去掉,使得字符串变为

    1 string str = "abc[你好]abc";

    显然使用正则表达式可以是

    1 string str = Regex.Replace(str, @"(\[你)[a-zA-Z]+(好\])", "$1$2");

      当然这里的解答绝对不是唯一的,因此给出的只是一个我想到的方法. 但是关键是这个情况是很特殊的. 首先,方括号“[]”中不见得就是汉字在两边,而且不见得就是你好;其次,对于中间不一定就是只有一串英文字母,比如还有可能是”你abc好abc啊”,那么此时就不太管用了.
    那么这里的问题便是:
      1、方括号内不确定有多少个汉子块与多少个英文块;
      2、方括号内不明确英文与汉字排列方式

      那么将问题化归一下,就好办了(注意,本文不见得给出的是最好方法,但是提供了一个思考问题的方法)

    汉字两边型
      由于问题是要将方括号内的英文字母去掉,所以无论方法括号内两端是什么,都可以使用C#语句:

    1 string str = Regex.Replace(str, @"(\[)[a-zA-Z]*(.+?)[a-zA-Z]*(\])", "$1$2$3");

      使得字符串中方括号两边变成汉字.
      也就是说所有的字符串都可以划归为如下模型

    …[中…中]…

     

    [中a中a中]型

      将字符串变为“汉字两边型”后,问题就是不明确两端汉字中有多少组引文字符,但是自己分析一下,去掉右边的汉字,那么字符串将变成由字符串片段“中a”的一个重复的循环组合,即:”中a”、”中a中a”、”中a中a中a”、… …
      那么问题就简单了,只要很好的解决“[中a中a中]型”的字符串,那么其他情况就可以利用循环解决了.
      第一步,从左往右依次去掉第一组英文(当然需要判断是否存在),例如,将一个的字符串”[中a中a中a中]”通过正则表达式替换变为”[中a中a中]”. 可以使用C#语句

    1 if(Regex.IsMatch(str, @"\[[^\]]+?[a-zA-Z]+[^\]]+\]"))
    2 {
    3 string str = Regex.Replace(str, @"(\[[^\]]+?)[a-zA-Z]+([^\]]+\])", "$1$2");
    4 }

      第二步,就很简单了,剩下的就是重复了,直到剩下“[中a中]型”. 实际上,当剩下该模式字符串时,依旧调用上面的方法,一样能实现将中间的英文去掉.

    分析一下匹配规则
      实际上现在已经把问题解决了,下面我说明一下我为何将正则表达式写成这样. 我以最后一次匹配为例. 

    1 string str = "a[中a中]a";
    2 if(Regex.IsMatch(str, @"\[[^\]]+?[a-zA-Z]+[^\]]+\]"))
    3 {
    4 string str = Regex.Replace(str, @"(\[[^\]]+?)[a-zA-Z]+([^\]]+\])", "$1$2");
    5 }

    分析:
    1、此时if判断中IsMatch判断是否匹配
      IsMatch中的正则表达式这么写“@”\[[^\]]+?[a-zA-Z]+[^\]]+\]””,表示先匹配中括号“[”开头,然后中间不允许有中括号结束的字符“]”,并且使用了取消贪婪模式使之后面的“[a-zA-Z]+”尽可能的匹配第一组英文字母. 这里匹配了str中的“[中a”. 然后剩下的“[^\]]+\]”匹配第一组引文字母结束后的所有字符,以及结束的中括号“]”. 因此返回的肯定是true.
    2、开始替换
      有了if的匹配以后,替换就很容易了,Replace方法中的正则表达式中首尾两个组分别匹配“[中”和“中]”,因此,“$1$2”就将中间的引文字母替换掉了.
      对于非最后一次匹配的情况,例如替换”[中a中a中]”,组1匹配“[中”,组2匹配“中a中]”,只是将左边的第一组英文替换掉了.

    整合结果

      通过前面的分析,想要将中括号里面的英文去掉,可采用的通用思维为
    -> 先去掉中括号内首尾英文字母
    -> 在利用循环,从左往右依次去掉一组组英文字符,直到英文字符为止

      结合前面的讨论,给出一个方法

    1 public static string MyReplace(string str)
    2 {
    3 str = Regex.Replace(str, @"(\[)[a-zA-Z]*(.+?)[a-zA-Z]*(\])", "$1$2$3");
    4 while (Regex.IsMatch(str, @"\[[^\]]+?[a-zA-Z]+[^]]+\]"))
    5 {
    6 str = Regex.Replace(str, @"(\[[^\]]+?)[a-zA-Z]+([^\]]+\])", "$1$2");
    7 }
    8 return str;
    9 }

      但是值得思考的是,此处不一定是绝对的解决方案,按照我的思维,一定会有更好的方法出现. 这里我只是给出了一个思考问题的方法,并拟定出了解决方案.

                                            2012年3月23日星期五 蒋坤










  • 相关阅读:
    python中list/tuple/dict/set的区别
    jquery修改ajax的header的字段origin方法,均被浏览器拒绝
    js判断上传文件的大小、类型、修改日期等信息
    js调试方法
    sqlmapapi的跨域访问Access-Control-Allow-Origin:*;ajax
    flask的文件上传和下载
    flask中的g、add_url_rule、send_from_directory、static_url_path、static_folder的用法
    python读写csv时中文乱码问题解决办法
    css中!important的作用
    项目经验——Sql server 数据库的备份和还原____还原数据库提示“介质集有2个介质簇,但只提供了1个。必须提供所有成员” .
  • 原文地址:https://www.cnblogs.com/jiangkun86/p/2413027.html
Copyright © 2011-2022 走看看