【问题标题】:Regex replace identical word with "and"正则表达式用“and”替换相同的单词
【发布时间】:2016-06-01 05:25:31
【问题描述】:

在下面的例句中:

绿衬衫绿帽子

是否可以使用正则表达式检测2个相同的单词并将第二个替换为and成为:

绿色衬衫和帽子


一个更难的字符串示例。这里需要替换第一个相同的词:

你是一个有艺术天赋和音乐天赋的人

应该变成:

你是一个有艺术和音乐天赋的人

【问题讨论】:

  • hm,您的第二个短语不仅仅是另一个示例,而是扩大了您初始语句的范围以找到一个可以检测和替换相同单词序列中的第 n 个单词的正则表达式?
  • 在您的第二个示例中,您正在分支到词汇分析,这在技术上超出了正则表达式的范围。
  • @RoYoMi 然而,js regex 是可能的:'你是一个有艺术天赋和音乐天赋的人'.replace(/(\b\S+\b)(.+ )(\1)\b/gi, '和$2$1');

标签: javascript regex


【解决方案1】:

说明

首先,正则表达式并不是最理想的解决方案,但我相信您有使用它的理由。

((\b[a-z]{1,}\b).*?)(\b\2\b)(.*)$

替换为: \1and\4

总结

此正则表达式将在字符串中找到两个相同的单词,并将第二个单词替换为and

示例

现场演示

https://regex101.com/r/yG3yM6/2

示例文本

Green shirt green hat
Green shirt greenish hat
You are an artistically gifted musically gifted individual

示例匹配

Green shirt and hat
Green shirt greenish hat
You are an artistically gifted musically and individual

说明

NODE                     EXPLANATION
----------------------------------------------------------------------
  (                        group and capture to \1:
----------------------------------------------------------------------
    (                        group and capture to \2:
----------------------------------------------------------------------
      \b                       the boundary between a word char (\w)
                               and something that is not a word char
----------------------------------------------------------------------
      [a-z]{1,}                any character of: 'a' to 'z' (at least
                               1 times (matching the most amount
                               possible))
----------------------------------------------------------------------
      \b                       the boundary between a word char (\w)
                               and something that is not a word char
----------------------------------------------------------------------
    )                        end of \2
----------------------------------------------------------------------
    .*?                      any character except \n (0 or more times
                             (matching the least amount possible))
----------------------------------------------------------------------
  )                        end of \1
----------------------------------------------------------------------
  (                        group and capture to \3:
----------------------------------------------------------------------
      \b                       the boundary between a word char (\w)
                               and something that is not a word char
----------------------------------------------------------------------
    \2                       what was matched by capture \2
----------------------------------------------------------------------
      \b                       the boundary between a word char (\w)
                               and something that is not a word char
----------------------------------------------------------------------
  )                        end of \3
----------------------------------------------------------------------
  (                        group and capture to \4:
----------------------------------------------------------------------
    .*                       any character except \n (0 or more times
                             (matching the most amount possible))
----------------------------------------------------------------------
  )                        end of \4
----------------------------------------------------------------------
  $                        before an optional \n, and the end of a
                           "line"
----------------------------------------------------------------------

额外积分

虽然在 OP 中没有解决,但如果有问题的单词使用非 a-z 字符,那么您可以将 [a-z] 替换为匹配非英语字符的 [a-z]|[^\x00-\x7F]。但是接下来我们需要将\b\2\b 更改为(?<=\s|^)\2(?=\s|$),这样我们才能确保正确匹配。

((\b(?:[a-z]|[^\x00-\x7F]){1,}\b).*?)((?<=\s|^)\2(?=\s|$))(.*)$

现场演示 https://regex101.com/r/wD8yF5/2

【讨论】:

  • 感谢您的工作代码和解释!如果不是正则表达式,什么会更理想?
  • 任何不得不问“这可以用正则表达式完成”的人,可能没有理由使用正则表达式......
  • @jmoreno,表面上我同意,但我认为问“这可以用正则表达式完成吗”这个问题是公平的,因为有很多问题可以用正则表达式解决,尽管很复杂生成的表达式可能会使外行难以维护。而那些不懂正则表达式的人是第一个对他们的使用嗤之以鼻的人
  • @Cyber​​Junkie,给定这样的短字符串,正则表达式可能会很好用。但是,要正确回答您的问题,我需要查看更多更难字符串的示例。
  • @Cyber​​Junkie “我在我的问题中又添加了一个示例。” 原始问题stackoverflow.com/revisions/37534118/1 已经解决了吗?
【解决方案2】:

修改this answer即可:

console.log( myFunc("Green shirt green hat") );
console.log( myFunc("Big red eyed rabbits red Ferrari") );

function myFunc(str) {
    return str.replace(/\b(\w+)(.+)(\1)\b/gi, "$1$2and");
}

【讨论】:

  • 最好在第一个捕获组之后和反向引用之前添加\b - 否则看看字符串alpha会发生什么
  • 您的正则表达式将 last 相同的单词替换为 'and',不一定是 second'Green shirt green hat green gloves'.replace(/\b(\w+)(.+)(\1)\b/gi, "$1$2and"); // Green shirt green hat and gloves
【解决方案3】:

您可以使用RegExp /(\bgreen\b)/ig,其中green 是要匹配的单词,String.prototype.replace(),当在替换函数中达到p2

p1, p2, ... nth 带括号的子匹配字符串,前提是 replace() 的第一个参数是 RegExp 对象。 (对应于 $1$2,等等。)例如,如果给定了/(\a+)(\b+)/p1\a+ 的匹配项,p2\b+ 的匹配项。

green 替换为and

var str = "Green shirt green hat green";
var re = function(m, p1, p2, index) {
  return p2 ? "and" : m
}
str = str.replace(/(\bgreen\b)/ig, re);
console.log(str);

【讨论】:

  • 这似乎只是因为第一个“Green”是大写的,因此与“green”不匹配。您的正则表达式与两个相同单词中的第二个不匹配。
  • @le_m “这似乎只是因为第一个“Green”大写,因此与“green”不匹配。您的正则表达式与两个相同单词中的第二个不匹配。” 嗯,这是原始问题中提供的字符串。返回 OP 中描述的预期结果。在 OP 更改字符串? “绿色”和“绿色”是不同的词;该问题也可以描述为匹配以小写“g”开头的“green”的第一次出现。你有什么建议?匹配"G""g"?
  • OP 想要一个通用的正则表达式来“检测 2 个相同的单词并替换第二个”。给定的短语只是一个例子。此外,/green{1,}/ 匹配 'green'、'greenn'、'greennn' 等,可能不是 OP 想要的。
  • @guest271314 鉴于这是一个编程问答网站,我确信 OP 正在寻找更具可扩展性的东西。在 2,719 多个答案中获得 35k 积分,我相信您已经看到不少问题,嗯……缺少内容或示例文本。
  • @RoYoMi 查看更新后的帖子。 “我相信您已经看到不少问题,嗯……缺少内容或示例文本。” 是的。给定原始字符串,原始stacksn-ps满足要求。
【解决方案4】:

您可以使用以下内容:

/(\b([^\s]+)\b.*?)\b\2\b/gi

测试用例:

var regex = /(\b([^\s]+)\b.*?)\b\2\b/gi;
'Green shirt green hat with blue shoes blue glasses'.replace(regex, '$1and')
  === 'Green shirt and hat with blue shoes and glasses';
'Orange colored oranges orange belts'.replace(regex, '$1and')
  === 'Orange colored oranges and belts';

Try it online

【讨论】:

    【解决方案5】:

    你的第一个例子的答案 - 我读为用'and'替换第一个重复单词的第二个 - 是:

    var str = 'Green shirt green hat';
    
    str = str.replace(/(\b\S+\b)(.+?)(\b\1\b)/i, '$1$2and');
    
    console.log(str);

    你的第二个例子的答案 - 我读为用'and'替换第一个重复的单词 - 是:

    var str = 'You are an artistically gifted musically gifted individual';
    
    str = str.replace(/(\b\S+\b)(.+?)(\b\1\b)/i, 'and$2$1');
    
    console.log(str);

    【讨论】:

      猜你喜欢
      • 2022-12-10
      • 2020-01-06
      • 2015-09-03
      • 1970-01-01
      • 1970-01-01
      • 2010-09-27
      • 1970-01-01
      • 1970-01-01
      • 2019-07-29
      相关资源
      最近更新 更多