首页 > 解决方案 > 如果捕获的匹配为空,如何避免捕获组?

问题描述

我想将这个词"custom"添加到主机名列表中,其子域可以用一些分隔符分隔。

例子:

news.google.com   -> custom.news.google.com
news/google/com   -> custom.news.google.com

dev.maps.yahoo.fr -> custom.dev.maps.yahoo.fr
dev/maps/yahoo/fr -> custom/dev/maps/yahoo/fr

这些字符串出现在具有更多内容的文档中,因此我尝试使用正则表达式和 JavaScript 的字符串replace函数来解决这个问题。

主机名和分隔符列表是预先定义好的和已知的。为了这个例子,我只显示了 2 个主机名 ( news.google.comand dev.maps.yahoo.com) 和 2 个分隔符 ( .and /),但还有更多。

单个字符串中的分隔符将始终相同,即不会出现dev/maps.yahoo/fr.

我想保持一致并在添加"custom".

我构建了这个长正则表达式:

const myRegex = /news\.google\.com|news\/google\/com|dev\.maps\.yahoo\.fr|dev\/maps\/yahoo\/fr/

(出于可读性目的,这是表达式:

/news\.google\.com//news\/google\/com//dev\.maps\.yahoo\.fr//dev\/maps\/yahoo\/fr/ )

(注意:重要的是要强调主机名列表是预先定义的并且是众所周知的,这就是为什么我对主机名进行“硬编码”而不使用诸如\w+or之类的标记\S+。例如,我可能想要替换news.google.com,但news2.google.com保持不变)。

但是,我不确定如何捕获分隔符(无论是.,/还是任何其他分隔符)。我尝试使用这样的捕获组:

const myRegex = /news(\.)google\.com|news(\/)google\/com|dev(\.)maps\.yahoo\.fr|dev(\/)maps\/yahoo\/fr/

但是,通过这样做,我创建了 4 个捕获组,并且只有一个分隔符(这只是一个简单的示例)。3 个捕获组将为空,其中一个将包含分隔符。我怎么知道它是哪个捕获组?

理想情况下,我想要这样的东西:

const myString = 'I navigated to news.google.com'; // For example
const myCustomString = myString.replace(
  myRegex,
  (match, <SEPARATOR_WRONG>) => `custom${SEPARATOR_WRONG}${match}`,
);

console.log(myCustomString); 
// will log 'I navigated to custom.news.google.com'

如果它们是空的,有没有办法跳过捕获的组?

标签: javascriptregex

解决方案


用于\1引用第一(\.|\/)组中捕获的分隔符,因此我们不必一遍又一遍地编写它。

const text = `I navigated to news.google.com
I navigated to news/google/com
I navigated to dev.maps.yahoo.fr
I navigated to dev/maps/yahoo/fr`;

const re = /\w+(\.|\/)(\w+\1)?(google|yahoo)\1\w+/g;
console.log(text.replace(re, (url, separator) => `custom${separator}${url}`));

鉴于评论中描述的新要求,这是一个替代解决方案:

const text = `I navigated to news.google.com
I navigated to news/google/com
I navigated to dev.maps.yahoo.fr
I navigated to dev/maps/yahoo/fr`;

const re = /(news|dev)(\.|\/)(google|maps)\2(com|yahoo)(\2fr)?/g;

console.log(text.replace(re, (url, prefix, separator) => `custom${separator}${url}`));

另一个替代解决方案:

const text = `I navigated to news.google.com
I navigated to news/google/com
I navigated to dev.maps.yahoo.fr
I navigated to dev/maps/yahoo/fr`;

const re = /news(\.)google\.com|news(\/)google\/com|dev(\.)maps\.yahoo\.fr|dev(\/)maps\/yahoo\/fr/g;

console.log(text.replace(re, url => 'custom' + url.match(/\.|\//)[0] + url));


推荐阅读