如果捕获的匹配项为空,如何避免捕获组?

Hec*_*rdo 6 javascript regex

我想在前面加上这个词 "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
Run Code Online (Sandbox Code Playgroud)

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

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

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

我想保持一致,并在添加时使用正确的分隔符"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
Run Code Online (Sandbox Code Playgroud)

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

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

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

但是,我不知道如何捕捉分离器(是否./或任何其他分隔符)。我尝试使用这样的捕获组:

const myRegex = /news\.google\.com|news\/google\/com|dev\.maps\.yahoo\.fr|dev\/maps\/yahoo\/fr/
Run Code Online (Sandbox Code Playgroud)

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

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

const myRegex = /news(\.)google\.com|news(\/)google\/com|dev(\.)maps\.yahoo\.fr|dev(\/)maps\/yahoo\/fr/
Run Code Online (Sandbox Code Playgroud)

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

Gir*_*rpa 2

用于\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}`));
Run Code Online (Sandbox Code Playgroud)

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

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}`));
Run Code Online (Sandbox Code Playgroud)

还有另一个替代解决方案:

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));
Run Code Online (Sandbox Code Playgroud)