混合正则表达式匹配的组



如果我有一个像SuMoTu 11:00AM - 1:00PM这样的输入,是否有可能只使用regex而不使用循环来生成Su 11:00AM - 1:00PM, Mo 11:00AM - 1:00PM, Tu 11:00AM - 1:00PM?

我想把11:00AM - 1:00PM和所有相关的日子SuMoTu混合。

当然,日子不会总是3天。时间从1天到5天不等。此外,日期将仅用2个字符表示。对于时间,它将始终是一个时间范围。

您可以尝试对捕获组和非捕获组使用向前看。下面是一个JavaScript示例:

const re = /([A-Z][a-z])(?=(?:[A-Z][a-z])+ (dd?:dd(?:AM|PM) - dd?:dd(?:AM|PM)))/g;
const replacement = '$1 $2, ';
console.log('Su 11:00AM - 1:00PM'.replace(re, replacement));
console.log('SuMo 11:00AM - 1:00PM'.replace(re, replacement));
console.log('SuMoTu 11:00AM - 1:00PM'.replace(re, replacement));
console.log('SuMoTuWe 11:00AM - 1:00PM'.replace(re, replacement));
console.log('SuMoTuWeTh 11:00AM - 1:00PM'.replace(re, replacement));

不使用循环

我认为答案是否定的,因为理论上的原因。正则表达式决定在输入字符串中执行什么操作。您要做的是匹配字符串的一部分(Su),打印它,然后跳到空格,抓住该行的其余部分,打印它,然后回溯到下一个2个字母的日子,然后重复。没有正则表达式。它可能有某种扩展的正则表达式,但它仍然是一个循环。

但是,您可以使用非常小的循环:

$ echo SuMoTu 11:00AM - 1:00PM | 
awk '{ time = $2 " - " $4; 
while(/^[SMTWTFS]/) { 
day = substr($1, 1, 2); 
$1 = substr($1, 3, length($1) - 2); 
print day, time 
} 
}'
Su 11:00AM - 1:00PM
Mo 11:00AM - 1:00PM
Tu 11:00AM - 1:00PM

解释:awk

将输入分解为由空格分隔的字符串,并将其编号为$1, $2,等等。只要输入字符串的开头是代表日期的大写字母,删除前两个字母,并将它们连同时间组件(在$2$4中捕获)一起打印。

这个循环是"small"在这个意义上,每个输入行被读取一次并扫描N次,其中N是前导字符串中的天数。

我怀疑你会找到比awk更快的方法来解决这个问题不使用编译语言。除非您在时间非常有限的情况下处理数百万行,否则也不需要这样做。我的小机器在3秒内处理了100万行。

最新更新