【问题标题】:replace non matches between delimiters替换分隔符之间的不匹配
【发布时间】:2014-07-08 09:42:48
【问题描述】:

我有一个输入字符串:

12345,3244,654,ffgv,87676,988ff,87657

我很难使用正则表达式将字符串中不是五位数字的所有项转换为常量 34567。所以,输出会是这样的:

12345,34567,34567,34567,87676,34567,87657

为此,我查看了两个选项:

  1. 否定字符类:没用,因为它不直接在这个表达式上执行,[^\d{5}],

  2. lookahead and lookbehind:这里的问题是它在此表达式的结果中不包含不匹配的部分 ,(?!\d{5})(?<!\d{5}), 用于替换/替换.

一旦找到所需的表达式,它将给出一个结果,以便可以使用标记区域(如\1\2)替换不匹配的部分。

正则表达式工具中是否有任何机制来实现上例中提到的输出?

编辑:我非常感谢那些回答非正则表达式解决方案的人,但如果您提供基于正则表达式的解决方案,我将更加感激。

【问题讨论】:

  • 那么,Python、JavaScript 还是 Perl?您使用什么语言?
  • @Сухой27:这个问题没有提到语言,而且正则表达式大多与语言无关。如果要添加语言标签,它应该是一个,并且只有一个,OP 提到的某处......
  • @Cerbrus 如果 Python 被错误标记,我很抱歉。恕我直言,正则表达式是从 Perl 演变而来的。 PHP 基于 Perl,就像基于 Ruby 的 RoR。我正在使用带有 PHP 后端的 JavaScript 工作。我目前正在重构网站,从繁重的服务器端查询执行转移到 MVC 框架。在 PHP 中,我在 PHP 中遇到了同样的问题,但我解决了使用 split 函数和围绕数组循环的工作。现在,它是 JavaScript。但是 Perl 中的正则表达式可以很容易地适应任何语言。我认为 Python 是 Perl 的脚本姐妹,所以我可能已经标记了 Python。
  • 所以你必须加上PHP标签,一个你一开始就错过的标签。顺便说一句,RoR 是 Ruby 框架,PHP 不是 Perl 框架。
  • 感谢您的建议。我已经重新标记了这个问题。

标签: javascript regex


【解决方案1】:

您不需要正则表达式。您可以使用str.split 先以逗号分隔字符串,然后检查每个项目的长度是否大于或等于 5 且仅包含数字(使用 str.isdigit)。最后使用str.join合并所有项目。

>>> s = '12345,3244,654,ffgv,87676,988ff,87657'
>>> ','.join(x if len(x) >= 5 and x.isdigit() else '34567' for x in s.split(','))
'12345,34567,34567,34567,87676,34567,87657'

Javascript 版本:

function isdigit(s){
    for(var i=0; i <s.length; i++){
       if(!(s[i] >= '0' && s[i] <= '9')){
           return false;    
        }
    }
    return true;
}
arr = "12345,3244,654,ffgv,87676,988ff,87657".split(",");

for(var i=0; i < arr.length; i++){
    if(arr[i].length < 5 || ! isdigit(arr[i])) arr[i] = '34567';
}
output = arr.join(",")

【讨论】:

  • 显然 OP 想在 JavaScript 中使用这个功能。您能否在答案中添加 JS 解决方案?
  • @Cerbrus 也添加了 JS 解决方案。
【解决方案2】:

尝试以下操作:/\b(?!\d{5})[^,]+\b/g

  • 它限制了单词边界之间的表达(\b),
  • 后跟对非五位数字 (!\d{5}) 的负前瞻,
  • 后跟, 之间的任何字符

const expression = /\b(?!\d{5})[^,]+\b/g;
const input = '12345,3244,654,ffgv,87676,988ff,87657';
const expectedOutput = '12345,34567,34567,34567,87676,34567,87657';

const output = input.replace(expression, '34567');
console.log(output === expectedOutput, expectedOutput, output);

【讨论】:

    【解决方案3】:

    这种方法使用/\b(\d{5})|(\w+)\b/g:

    • 我们在边界上匹配 (\b)
    • 我们的第一个捕获组捕获“好字符串”
    • 我们较松散的捕获小组得到了剩余(坏字符串)
    • 我们的 replacer() 函数知道区别

    const str = '12345,3244,654,ffgv,87676,988ff,87657';
    const STAND_IN = '34567';
    
    const massageString = (str) => {
        const pattern = /\b(\d{5})|(\w+)\b/g;
        const replacer = (match, goodstring, badstring) => {
            if (goodstring) {
              return goodstring;
            } else {
              return STAND_IN;
            }
        }    
        const r = str.replace(pattern,replacer);
        return r;
    };
    
    console.log( massageString(str) );

    【讨论】:

      【解决方案4】:

      我认为以下内容适用于不超过 5 个字母数字字符的值:

      (,(?!\d{5})\w{1,5})
      

      如果超过 5 个字母数字字符,则删除上述表达式中的 5

      (,(?!\d{5})\w{1,})
      

      您可以使用以下方式替换:

      ,34567
      

      您可以看到demo on regex101。当然,对于特定语言(python、perl 或 JS)也可能有更快的非正则表达式方法

      【讨论】:

        猜你喜欢
        • 2021-03-11
        • 2011-11-18
        • 1970-01-01
        • 2018-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-22
        • 2020-10-30
        相关资源
        最近更新 更多