正则表达式匹配一个或多个字母或数字包围的所有单个下划线
Posted
技术标签:
【中文标题】正则表达式匹配一个或多个字母或数字包围的所有单个下划线【英文标题】:Regex match all single underscores surrounded in one or more letters or numbers 【发布时间】:2016-01-12 00:34:20 【问题描述】:我正在尝试查找所有单下划线,这些单下划线被一个字符串中的另外一个字母或数字包围。例如:
ChIJww8705e81qjAgU_IJww8705ZZkW_e81qjAg_ChIJww8
*注意:字符串的长度和下划线的个数是未知的。该字符串还可以同时包含多个下划线。 *
我确信这很容易,但我对正则表达式不是超级精通。这是我目前所拥有的,但它只匹配第一次出现。
[a-zA-Z0-9]+(_)+[a-zA-Z0-9]
最终目标是用另一个字符替换下划线。
【问题讨论】:
你必须使用正则表达式吗?否则,只需执行 'ChIJww8705e81qjAgU_IJww8705ZZkW_e81qjAg_ChIJww8.split("_") ,结果数组的大小将为您提供答案。 啊,我应该提到我匹配的字符串可能连续包含多个下划线。例如: foo___bar___rad 我只需要带有单个下划线并被字符包围的那些 【参考方案1】:在像a_b_c
这样的情况下,为避免b
被包括第一个下划线在内的匹配所消耗(这将阻止第二个下划线被匹配),您可以使用前瞻,它会检查当前的匹配位置但不消耗任何输入。 (更简单的是前瞻和后瞻,但 javascript 不支持后瞻。)
/[a-zA-Z0-9]_(?=[a-zA-Z0-9])/g
除此之外,您只能获得一场比赛的唯一原因是您没有包含/g
(全局)标志。 /g
影响String#match
,使其返回所有匹配项而不是第一个匹配项的所有捕获,String#replace
导致它替换所有实例而不只是第一个实例,RegExp#exec
使其继续匹配从上一场比赛开始,所以你可以在循环中使用它。
这里将所有此类下划线替换为固定字符串**
:
s.replace(/([a-zA-Z0-9])_(?=[a-zA-Z0-9])/g, '$1**');
如果您确实需要完整的环境来进行替换,您可以将+
量词保留在第一组中,并将捕获组放在前瞻中。 (这仍然有效!)
一个例子可能会让这更清楚——这是一个将每对数字添加到一个字符串中的例子,比如150_297_832
:
var s = '150_297_832';
var result = s.replace(/(\d+)_(?=(\d+))/g, function (match, left, right)
var sum = parseInt(left, 10) + parseInt(right, 10);
return ' (' + sum + ') ';
);
// result = ' (447) (1129) 832';
// 447 is 150 + 297, 1129 is 297 + 832, 832 was not replaced
【讨论】:
【参考方案2】:试试这个正则表达式:
([a-zA-Z0-9])_([a-zA-Z0-9])
你可以像这样用'-'替换它
str.replace(/([a-zA-Z0-9])_([a-zA-Z0-9])/g, "$1-$2")
您可以添加任何其他字符或字符串来代替“-”
此正则表达式匹配(A-Z 或 a-z 或 0-9)、下划线和(A-Z 或 a-z 或 0-9)
说明:
[a-zA-Z0-9]
匹配小写或大写字母和数字。
()
:制作一组匹配,([a-zA-Z1-9])
制作一组,以便稍后在解决方案中使用。
和 _
显然匹配下划线。
替换字符串中的$1
和$2
指的是正则表达式中的第一个和第二个匹配组。
【讨论】:
请为未来的访问者和 OP 解释正则表达式匹配的内容。\w
已经是\d
的超集,它还包括_
,它可能不应该这样做。它应该是[a-z\d]
或[a-zA-Z\d]
而不是[\d\w]
。为了字符类的可读性,很多人可能会使用0-9
而不是\d
,因为在字符类中\d
并没有节省多少。
已更新 @DavidThomas,感谢您提及 ShadowRanger,但在 David 发表评论后已经对其进行了更新
@torazaburo nop .. 因为您的解决方案效果很好并且解释清楚.. +1 :)【参考方案3】:
你快到了,考虑一下你的正则表达式:
[a-zA-Z0-9]+ // a-z, A-Z and 0-9, matched one or more times (greedy)
(_)+ // _ in capture group, matched one or more times (greedy)
[a-zA-Z0-9] // a-z, A-Z and 0-9, matched exactly one time
下划线前面不需要匹配多个字符,也不需要匹配多个下划线:
/[a-zA-Z0-9]_[a-zA-Z0-9]/g
// ^ Note the global flag
您也可以使用\w
,它等于:[A-Za-z0-9_]
,但请注意它也匹配下划线:
/[\w]_[\w]/g
将其与匹配组和.replace(search, replacement)
捆绑在一起:
// Replace all underscores with dashes (-)
var str = 'ChIJww8705e81qjAgU_IJww8705ZZkW_e81qjAg_ChIJww8';
str.replace(/([\w])_([\w])/g, '$1-$2');
// ^ ^
// | Refers to second match group `([\w])`
// Refers to first match group `([\w])`
【讨论】:
如果字符串有多个下划线,这个不起作用。例如:ChIJww8705e81qjAgU___IJww8705ZZkW_e81qjAg___ChIJww8
在该示例中,我只想捕获 W 和 e 字符之间的下划线。以上是关于正则表达式匹配一个或多个字母或数字包围的所有单个下划线的主要内容,如果未能解决你的问题,请参考以下文章