【问题标题】:Can we search regexp from the middle of a text back to beginning?我们可以从文本中间搜索正则表达式吗?
【发布时间】:2019-08-02 11:05:52
【问题描述】:

我有一个文本和一个“标记”(regexp = "error")。我可以找到“标记”的位置,但基本目标是文章的数量,它位于“标记”之前。简而言之,我需要找到带有regexp = /\d{2}\\/\d{2}\\/\d{4}/) 的号码。在我的情况下需要找到09/09/4567。我该怎么做呢?

text = "harum voluptatibus laboriosam blanditiis similique commodi labore 09/09/4567 repellat error quasi animi nostrum magnam, ab asperiores unde porro! ipsum dolor sit amet, consectetur adipisicing elit. Velit, delectus esse aperiam quod aliquid sunt iure ducimus. Nesciunt eveniet, possimus 09/09/4568 adipisci accusamus reiciendis , quos pariatur, sapiente rem quaerat cumque."
text.match("error");

【问题讨论】:

  • 看起来你需要像/\d{2}\/\d{2}\/\d{4}(?=(?:(?!\d{2}\/\d{2}\/\d{4})[^])*?error)/g 这样的东西,见demo

标签: javascript regex


【解决方案1】:

你可以使用

/\d{2}\/\d{2}\/\d{4}(?=(?:(?!\d{2}\/\d{2}\/\d{4})[^])*?error)/g

请参阅regex demo

要将模式匹配为整个单词,请添加单词边界:

/\b\d{2}\/\d{2}\/\d{4}\b(?=(?:(?!\b\d{2}\/\d{2}\/\d{4}\b)[^])*?\berror\b)/g

详情

  • \d{2}\/\d{2}\/\d{4} - 两位,/,两位,/,四位
  • (?=(?:(?!\d{2}\/\d{2}\/\d{4})[^])*?error) - 从当前位置向右,应该有一个匹配
    • (?:(?!\d{2}\/\d{2}\/\d{4})[^])*?- 任何字符([^],您也可以使用[\s\S]),0 次或更多重复但尽可能少(*?),不会启动上述\d{2}\/\d{2}\/\d{4} 模式
    • error - error 子字符串。

JS 演示:

var text = "harum voluptatibus laboriosam blanditiis similique commodi" + 
 "labore 09/09/4567 repellat error quasi animi nostrum magnam, ab asperiores unde porro! "+
 "ipsum dolor sit amet, consectetur adipisicing elit. Velit, delectus esse aperiam quod " +
 "aliquid sunt iure ducimus. Nesciunt eveniet, possimus 09/09/4568 adipisci accusamus " + 
 "reiciendis , quos pariatur, sapiente rem quaerat cumque.\n" +
 "one 01/01/1111 two error 02/02/2222 three four 03/03/3333 five error";
var rx = /\d{2}\/\d{2}\/\d{4}(?=(?:(?!\d{2}\/\d{2}\/\d{4})[^])*?error)/g;
console.log(text.match(rx));

【讨论】:

  • @T.J.Crowder 这是基于tempered greedy token
  • 谢谢!我不得不承认,当我在看这个表达式时,我完全错过了负前瞻。 (我受不了了。)现在说得通了——而且很酷。
【解决方案2】:

在评论中我问:

你想从"one 01/01/1111 two error 02/02/2222 three four 03/03/3333 five error" 得到哪两个结果?你想要01/01/111102/02/2222,还是01/01/111103/03/3333? (请注意,“错误”在该字符串中仅出现两次。)

你回答了

我需要 [01/01/1111, 03/03/3333]

我不能用一个正则表达式来做到这一点。我试过/.*(\d\d\/\d\d\/\d\d\d\d).*?error/,但得到的只是03/03/3333

找到error,然后寻找最接近它的数字就可以了:

const text = "one 01/01/1111 two error 02/02/2222 three four 03/03/3333 five error blah blah";
const rexError = /error/g;
const rexDigits = /.*(\d\d\/\d\d\/\d\d\d\d)/;
let result;
let last = 0;
while (result = rexError.exec(text)) {
  result = rexDigits.exec(text.substring(last, result.index))
  if (result) {
    console.log(result[1]);
  }
}

开头的.* 是跳过第一组数字,而是让匹配到达最后一组。

【讨论】:

  • 好吧,如果我们有两个或更多匹配&
  • @piperpiper - 从根本上说,添加g 标志并反复调用exec,直到你得到null。但问题是:你想从"one 01/01/1111 two error 02/02/2222 three four 03/03/3333 five error" 得到哪两个结果?你想要01/01/111102/02/2222,还是01/01/111103/03/3333? (请注意,“错误”在该字符串中仅出现两次。)
  • 我需要带有数字的数组(找到匹配项)。需要文本中的所有数字,在我们有单词(“错误”)之后(在右侧)
  • @piperpiper - 这不能回答我的问题。对于我给你的字符串,你期待什么结果?
  • @T.J.Crowder 我已经完成了,请检查我的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-08
  • 1970-01-01
  • 1970-01-01
  • 2014-04-06
  • 1970-01-01
相关资源
最近更新 更多