正则表达式使用技巧_3个带有正则表达式的整洁技巧

正则表达式使用技巧

我想向您展示可以使用正则表达式执行的三项巧妙的操作,它们为某些非常棘手的问题提供了巧妙的解决方案:

  1. 删除评论
  2. 使用替换回调
  3. 使用不可见的分隔符

1.删​​除评论

正则表达式使单字符定界符的工作变得轻松,这就是为什么从字符串中删除标记如此容易的原因:

str = str.replace(/(<[\/]?[^>]+>)/g, '');

真正完成工作的是字符类中的否定:

[^>]

意思是“除<之外的任何东西 。 因此,表达式将查找起始标签定界符和可能的斜杠,然后查找除结束标签定界符之外的所有内容,然后查找定界符本身。 简单。

但是,注释并不是那么简单,因为注释定界符由多个字符组成 。 例如, CSS和JavaScript中的多行注释以/*开头,以*/结束,但是在这两个定界符之间可以有任意数量的不相关星号

我经常在评论中使用多个星号,以表明我刚刚发现的错误的严重性,例如:

/*** this is a bug with 3-star severity ***/

但是,如果我们尝试使用单个否定字符来解析它,它将失败:

str = str.replace(/(\/\*[^\*]+\*\/)/g, '');

但是,用正则表达式不可能说: “除[此字符序列]之外的任何东西” ,我们只能说: “除[这些单个字符之一]之外的任何东西”

因此,这是我们需要的正则表达式:

str = str.replace(/(\/\*([^*]|(\*+[^*\/]))*\*+\/)/gm, '');

该表达式通过查看不相关的字符来处理不相关的字符-允许加星号,只要它们后面不加斜杠,直到找到一个即是,这就是注释的结尾。

因此它说:“ /然后* (然后是*或任何数量的*然后是/除外)(以及该实例的任何数量的实例),然后是任意数量的*然后/ ”。

(语法看起来特别复杂,因为*/都是正则表达式中的特殊字符,因此模棱两可的文字必须转义。还要注意表达式末尾的m标志,表示多行 ,并指定正则表达式应跨多行文本进行搜索。)

然后,使用相同的原理,我们可以使表达式适应搜索任何类型的复杂定界符。 这是与HTML注释匹配的另一个:

str = str.replace(/(<!\-\-([^\-]|(\-+[^>]))*\-+>)/gm, '');

这是CDATA部分的内容:

str = str.replace(/(<\!\[CDATA\[([^\]]|(\]+[^>]))*\]+>)/gm, '');

2.使用替换回调

还可以将replace函数作为第二个参数传递给回调函数,这在无法用简单表达式描述所需替换的情况下非常有用。 例如:

isocode = isocode.replace(/^([a-z]+)(\-[a-z]+)?$/i, 
  function(match, lang, country)
  {
    return lang.toLowerCase() 
      + (country ? country.toUpperCase() : '');
  });

该示例规范了语言代码中的大写字母-因此"EN"将变为"en" ,而"en-us"将变为"en-US"

传递给回调的第一个参数始终是完全匹配项,然后每个后续参数都与反向引用相对应(即arguments[1]是字符串替换将称为$1 ,依此类推)。

因此,以"en-us"作为输入,我们将获得三个参数:

  1. "en-us"
  2. "en"
  3. "-us"

然后,所有功能所要做的就是强制执行适当的情况,重新组合部件并返回它们。 回调返回的内容是替换本身返回的内容。

免费学习PHP!

全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。

原价$ 11.95 您的完全免费

但是实际上我们不必分配返回值(或根本不返回),如果不这样做,那么原始字符串将不受影响。 这意味着我们可以将replace用作通用字符串处理器 -从字符串中提取数据而无需更改它。

这是另一个示例,该示例将上一节中的多行注释表达式与提取并保存每个注释文本的回调结合在一起:

var comments = [];
str.replace(/(\/\*([^*]|(\*+[^*\/]))*\*+\/)/gm, 
  function(match)
  {
    comments.push(match);
  });

由于未返回任何内容,因此原始字符串保持不变。 尽管如果我们想提取删除注释,我们可以简单地返回并分配一个空字符串:

var comments = [];
str = str.replace(/(\/\*([^*]|(\*+[^*\/]))*\*+\/)/gm, 
  function(match)
  {
    comments.push(match);
    return '';
  });

3.使用不可见的分隔符

使用标准定界符时,提取内容非常好,但是如果您使用仅程序知道的自定义定界符怎么办? 问题在于字符串可能已经包含您的定界符 ,一个字符一个字符,然后您要做什么?

好吧,最近我想到了一个非常可爱的技巧,它不仅避免了这个问题,而且使用起来就像我们一开始看到的单字符类一样简单! 技巧是使用文档不能包含的unicode字符

最初,我尝试使用未定义的字符进行此操作,并且确实可以使用,但是假设任何此类字符始终未定义(或者文档无论如何都不会包含该字符)是不安全的。 然后,我发现Unicode实际上为这种事情专门保留了一组代码点-所谓的noncharacters ,它将永远不会用于定义实际字符。 有效的Unicode文档不允许包含非字符,但是程序可以在内部出于自身目的使用它们。

我当时正在使用CSS处理器,因此在解析选择器之前需要删除所有注释,因此它们不会混淆选择器匹配的表达式。 但是必须在源代码中将它们替换为占用相同行数的内容,以便行号保持准确。 然后,稍后必须将它们添加回源中,以进行最终输出。

因此,首先我们使用正则表达式回调提取并保存注释。 回调返回匹配项的副本,在该副本中,所有非空格都转换为空格,并且在两侧均以非字符定界:

var comments = [];
csstext = csstext.replace(/(\/\*([^*]|(\*+([^*\/])))*\*+\/)/gm, 
  function(match)
  {
    comments.push(match);
    return '\ufddf' + match.replace(/[\S]/gim, ' ') + '\ufddf';
  });

这将创建一个注释数组,其注释顺序与它们留下的空格相同,而空格本身占用的行数与原始注释相同。

然后,只需将每个定界空间替换为相应的已保存注释,即可恢复原始字符,并且由于定界符是单个字符,因此我们只需要一个简单的字符类来匹配每对字符

csstext = csstext.replace(/(\ufddf[^\ufddf]+\ufddf)/gim, 
  function()
  {
    return comments.shift();
  });

多么简单!

翻译自: https://www.sitepoint.com/3-neat-tricks-with-regular-expressions/

正则表达式使用技巧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值