使用正则表达式从键值对的值中提取子字符串

Extract a substring from value of key-value pair using regex

我在日志中有一个字符串,我想根据正则表达式屏蔽值。

例如:

"email":"testEmail@test.com", "phone":"1111111111", "text":"sample text may contain email testEmail@test.com as well"

正则表达式应该屏蔽

  1. email 值 - 在 "email" 和 "text"
  2. 之后的字符串中
  3. phone个数

期望输出:

"email":"*****", "phone":"*****", "text":"sample text may contain email ***** as well"

我能做的是单独屏蔽电子邮件和 phone,但不屏蔽 "text" 之后字符串中的电子邮件 ID。

正则表达式发展至今:

(?<=\"(?:email|phone)\"[:])(\")([^\"]*)(\")

https://regex101.com/r/UvDIjI/2/

由于您在第一部分中没有通过匹配双引号来匹配电子邮件地址,因此您也可以通过不匹配双引号来匹配文本中的电子邮件地址。

实现此目的的一种方法是使用环视和 alternation 获得匹配项。然后用 *****

替换匹配项

请注意,您不必转义双引号,冒号也可以不使用字符 class.

(?<="(?:phone|email)":")[^"]+(?=")|[^@"\s]+@[^@"\s]+

说明

  • (?<="(?:phone|email)":") 断言左边是 "phone":" 或 "email":"
  • [^"]+(?=") 不匹配双引号,确保最后有双引号
  • |
  • [^@"\s]+@[^@"\s]+ 通过使用不匹配双引号或@
  • 的否定字符 class 来匹配 email like 模式

regex demo

Meta Sequence Word Boundary \b & Alternation |

输入的字符串模式有引号或 spaces 包裹在目标周围,它们都被认为是非单词。所以这个:“\bemailPattern\b”和这个:space\bemailPattern\bspace 是匹配项。交替赋予一条线两条线的力量。搜索 emailPattern OR phonePattern.

/(\b\w+?@\w+?\.\w+?\b|[0-9]{10})/g;
  • (字边界(左边一个非字)\b
  • 一个或多个单词字符\w+?
  • 文字 @
  • 一个或多个单词字符\w+?
  • 转义文字 .
  • 一个或多个单词字符\w+?
  • 单词边界(右边一个非单词)\b
  • |
  • 10个连续数字[0-9]{10})
  • g局部标志在第一次匹配后继续搜索。

演示

let str = `"email":"testEmail@test.com", "phone":"1111111111", "text":"sample text may contain email testEmail@test.com as well"`;

const rgx = /(\b\w+?@\w+?\.\w+?\b|[0-9]{10})/g;

let res = str.replace(rgx, '*****');

console.log(res);

您当前的 RegEx 试图一次完成太多。您最好拆分条件并分别处理它们。我假设输入将始终遵循您示例的结构,没有边缘情况:

  1. 电子邮件:
    • \w+@.+?(?="|\s) - 在电子邮件中,每个以 @ 开头的字符始终是一个单词字符,因此使用 \w+@ 足以捕获电子邮件的前半部分。至于后半部分,我使用了带有惰性量词 (+?) 的通配符 (.) 来尽快停止捕获,并将其与检查双引号或空格的正向前瞻相结合((?="|\s)) 所以要捕获 "email""text" 属性中的电子邮件。 Lookarounds are zero-length assertions 因此他们不会被捕获。
  2. Phone个数:
    • (?<="phone":")\d+ - 这里我只是在回顾中使用前缀 "phone":" 然后只捕获数字 \d+.

结合这两个条件,您就有了 RegEx:\w+@.+?(?="|\s)|(?<="phone":")\d+.

Regex101: https://regex101.com/r/UvDIjI/3