当数据不遵循单一格式时,如何编写正则表达式



我有一个Javascript字符串:

let entries = `23-05-1990  Some heading
27-05-1990  Liar Liar
29-05-1990  Another Heading
30-05-1990  50/50
31-05-1990  My day`

使用regex,我需要处理这个字符串并生成两个数组:

// 1) date array:
date = ["23-05-1990","27-05-1990", "29-05-1990", "30-05-1990", "31-05-1990"]
// 2) headings array
headings = ["Some heading", "Liar Liar" ,"Another Heading",  "50/50", "My day"]

到目前为止,这很简单:通过换行进行拆分,然后将每个单独的日期标题传递给regex。获取日期和标题,并将它们附加到各自的数组中。

但问题是我没有一个一致的数据格式。

有些数据是这种格式的。即标题在日期之前

`Liar Liar          27-05-1990  
Another Heading    29-05-1990  
50/50              30-05-1990  
My day             31-05-1990  `

标题和日期之间可能有分隔符。

`23-05-1990 : Some heading
27-05-1990 : Yes Man`
`29-05-1990: Another Heading`
`30-05-1990 - 50/50
31-05-1990 - My day`

所以,日期和标题会在那里(我们不知道哪一个先出现(,但分隔符可能存在,也可能不存在。

此外,

  1. 分离器是下面列出的三种之一:

    "quot;(空格(-&":">

  2. 标题不能以字母表或int以外的任何字符开始或结束

您可以匹配以下正则表达式。日期字符串将在捕获组1或4中,另一个将为空。标题将在捕获组2或3中,另一个将为空。

^(?:(d{2}-d{2}-d{4}) *[-:]? *([A-Zd].*)|([A-Zd].*)(?<![ :-]) *[-:]? *(d{2}-d{2}-d{4}))$

启动发动机!

如链接所示,"$1$4"返回日期字符串,"$2$3"返回标题。

Javascript的正则表达式引擎执行以下操作。

^                      : assert beginning of string
(?:                    : begin non-capture group
(d{2}-d{2}-d{4})  : match date and save to capture group 1
[ ]*[-:]?[ ]*        : match 0+ spaces, optional '-' or ':',
0+ spaces 
([A-Zd].*)          : match heading and save to capture group 2
|                      : or
([A-Zd].*)          : match heading and save to capture group 3
(?<![ :-])           : negative lookbehind asserts previous
character is neither ' ', ':' nor '-'
[ ]*[-:]?[ ]*        : match 0+ spaces, optional '-' or ':',
0+ spaces
(d{2}-d{2}-d{4})  : match date and save to capture group 4 
)                      : end non-capture group
$                      : assert end of string

这是有效的,但它不考虑重复,所以如果这是一个问题,那么您可以在之后过滤掉这些,或者在数组中使用键/值对。

while循环的一部分来自regex101.com

const regexes = [
/((?<date>d{2}-d{2}-d{4})[ :-]+(?<title>.*)[rn])/gm,
/(?<title>.*)[ :-]+((?<date>d{2}-d{2}-d{4})[rn])/gm
];
const str = `23-05-1990  Some heading
27-05-1990  Liar Liar
29-05-1990  Another Heading
30-05-1990  50/50
31-05-1990  My day
Liar Liar          27-05-1990
Another Heading    29-05-1990
50/50              30-05-1990
My day             31-05-1990
23-05-1990 : Some heading
27-05-1990 : Yes Man
29-05-1990: Another Heading
30-05-1990 - 50/50
31-05-1990 - My day`;
let output = [];
regexes.forEach(regex => {
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
output.push([m.groups.date.trim(), m.groups.title.trim()]);
}

});
console.log(output);

输出为:

[
[ '23-05-1990', 'Some heading' ],
[ '27-05-1990', 'Liar Liar' ],
[ '29-05-1990', 'Another Heading' ],
[ '30-05-1990', '50/50' ],
[ '31-05-1990', 'My day' ],
[ '23-05-1990', 'Some heading' ],
[ '27-05-1990', 'Yes Man' ],
[ '29-05-1990', 'Another Heading' ],
[ '30-05-1990', '50/50' ],
[ '27-05-1990', 'Liar Liar' ],
[ '29-05-1990', 'Another Heading' ],
[ '30-05-1990', '50/50' ],
[ '31-05-1990', 'My day' ]
]

最新更新