动态清理字符串

Cleaning Strings dynamically

我在学习 puppeteer 时将网页作为一个有趣的小项目进行抓取,在那段时间里,我 运行 在清理字符串以获取 有用的数据。我想出了一些从他们那里提取我想要的数据的简单方法,但我 运行 陷入边缘情况,我不知道最好的处理方式。

取这个字符串

Round 1 - Foo Bar (SchoolName) over John (JC) Cena (Fake School Name) (Fall 1:19)

我要获取的数据

Round 1- 对我没用,它们在整个应用程序中遵循相同的结构。因此,使用仅选择这些项目所在位置的索引的方法应该非常简单。

这个字符串中最重要的索引是over所在的位置。一旦找到它,我就可以搜索它周围的索引,找到我需要的其余信息在哪里。

let findOver = arr.indexOf('over')
let winnerName = arr[over - 3].concat(' ', arr[over - 2])
let winnerSchool = summaryBreakUp[over - 1]

这对上面的字符串有效,至少对左侧有效。它获取获胜者的名字和姓氏并将它们连接起来。

我的问题是当字符串看起来不像左侧时,我如何 考虑上面的边缘情况。

我可以搜索所有 ( && ) 并捕获其中的所有数据以获得 School Names 但随后我需要筛选一种方法来确定哪一个是学校和哪个是昵称

如有任何指示,我们将不胜感激。我还会 post 一些更多的例子,以防其他人想尝试一下。

这是对未指定对手的胜利。
Michael Macontish (Fairview) over Unknown (For.)
没有给出回合
John Heflin (Arlington) over Random Kid (Mistview) (Fall 1:59)
没有 下降 给予
Round 2 - Logan Paul George (High School) over Dontae Inverse (Jackson County) (Dec 3-0)

使用正则表达式和捕获组来获取您感兴趣的位,您可能需要做一些小的整理工作。

您可以使用许多模式(我相信这不是最好的,但它是一个开始):

([\w\s\(\)]+)\s\(([\s\w\.]+)\)\sover\s([\w\s\(\)]+)\s\(([\s\w\.]+)\)

这与名字相匹配

  • 任何字母数字、下划线、空格或括号
  • 出现一次或多次

后跟左括号,后跟学校为

  • 任何空格、字母数字、下划线或句点
  • 出现一次或多次

后跟一个右括号,然后是空格,然后是单词“over”,再次是空格,然后重复名称和学校模式。其他一切都被忽略。


用法:当您在 javascript 中使用正则表达式时,捕获组最终作为结果数组中的元素。整个匹配是第一个元素,每个附加元素按顺序表示捕获组。此表达式中有 4 个捕获组,因此您最终会得到代表 name1、school1、name2 和 school2 的元素 1-5。

const re = /([\w\s\(\)]+)\s\(([\s\w\.]+)\)\sover\s([\w\s\(\)]+)\s\(([\s\w\.]+)\)/

const input = [
  'Round 1 - Foo Bar (SchoolName) over John (JC) Cena (Fake School Name) (Fall 1:19)',
'Michael Macontish (Fairview) over Unknown (For.)',
'John Heflin (Arlington) over Random Kid (Mistview) (Fall 1:59)',
'Round 2 - Logan Paul George (High School) over Dontae Inverse (Jackson County) (Dec 3-0)'
]


input.forEach( i => {
   console.log(i.match(re))
})

作为替代模式,您可以使用非贪婪点扩大匹配范围 .*? 以匹配任何字符或否定字符 class [^ 以排除允许的内容待匹配。

开始模式,可选择匹配开头的部分 -

要匹配末尾括号之间的正确部分,您可以断言括号之间的部分没有 - 或 : 数字之间使用负先行。

(?:.*?\s+-\s+)?([^()]+)\s+\(([^()]+)\)\s+over\s+(.*)\s+\((?![^()]*\d[-:]\d[^()]*\))([^()]*)\)

模式匹配:

  • (?:.*?\s+-\s+)? 可选择匹配以 <code> - </code>
  • 结尾的部分
  • ([^()]+) 捕获 组 1 以匹配除 ()
  • 之外的任何字符
  • \s+ 匹配 1+ 个空白字符
  • \(([^()]+)\) 匹配 ( 然后捕获 组 2 中除 () 之外的任何字符并匹配 )
  • \s+over\s+Matchover` 在 1 个或多个空白字符之间
  • (.*) 捕获 组 3
  • 中的任何字符
  • \s+ 匹配 1+ 个空白字符
  • \( 匹配 (
  • (?![^()]*\d[-:]\d[^()]*\)) 否定前瞻,断言括号之间没有 :- 之间的数字
  • ([^()]*) 如果断言为真,则捕获 group 4
  • 中除 () 之外的任何字符
  • \) 匹配 )

看到一个regex demo

const regex = /(?:.*?\s+-\s+)?([^()]+)\s+\(([^()]+)\)\s+over\s+(.*)\s+\((?![^()]*\d[-:]\d[^()]*\))([^()\n]*)\)/;
[
  "Round 1 - Foo Bar (SchoolName) over John (JC) Cena (Fake School Name) (Fall 1:19)",
  "Michael Macontish (Fairview) over Unknown (For.)",
  "John Heflin (Arlington) over Random Kid (Mistview) (Fall 1:59)",
  "Round 2 - Logan Paul George (High School) over Dontae Inverse (Jackson County) (Dec 3-0)"
].forEach(s => console.log(s.match(regex)));