Regex.Replace 到 deidentify/normalize 分栏文字

Regex.Replace to deidentify/normalize columnar text

VB2010:我正在使用 RegEx 对一段文本进行去标识化处理,并对文本进行规范化。也就是说,取几行文本,将名称和确认码去标识化,然后将文本规范化,使数据按列排列。除了最后一部分,我几乎拥有所有内容,其中确认代码前面有可变数量的点和一个长度为 2 到 4 个字符或可能丢失的包 ID。

    'regex
    Dim MyRegex As Regex = New Regex("(?<pre>^\s{0,2}(\d{1,3})\s(\d\d))(.+?)(?<post>\.\.(\d{1,3})\." + "(\w)\s((\w+?|\.\.)))(?<dots>\.+)(\w{6})", RegexOptions.IgnoreCase Or RegexOptions.Multiline)

    'this is the replacement string
    Dim replacement As String = "${pre}******/*****${post}${dots}******"

    'replace the matched text in the InputText using the replacement pattern
    Dim result As String = MyRegex.Replace(Input, replacement)

我的测试输入每行都有一个数字、名称、编号、杂项代码、包裹 ID 和确认代码:

  1 01SMITH/CH..1.A E2T......AAABBB
  2 01MTC..1.A ..............CCCDDD
  3 01GRIFFIN/JOHN..1.A E2...EEEFFF
  4 01EL/MARY..1.Z E2XT......GGGHHH
  5 02BUBBA/BILLY..2.A E2....IIIJJJ
  6 01HILL/THOR..1.A E2WW....KKKLLL

到目前为止我的输出:

  1 01******/*****..1.A E2T......******
  2 01******/*****..1.A ..............******
  3 01******/*****..1.A E2...******
  4 01******/*****..1.Z E2XT......******
  5 02******/*****..2.A E2....******
  6 01******/*****..1.A E2WW....******

我正在取消识别名称和确认码,但确认码之前的代码包 ID 是可变的,因此会丢弃我的柱状输出。有点卡在它的最后部分,但真的很接近。我的目标是一个一个地做正则表达式,但这可能是不可能的。是否可以填充正则表达式替换?

更新解决方案:

    'regex (added one more group for the package id so I can determine its length)
    Dim MyRegex As Regex = New Regex("(?<pre>^\s{0,2}(\d{1,3})\s(\d\d))(.+?)(?<post>\.\.(\d{1,3})\.(\w)\s(?<pkid>(\w+?|\.\.)))(?<dots>\.+)(\w{6})", RegexOptions.IgnoreCase Or RegexOptions.Multiline)

    'use the MatchEvaluator to examine each match and adjust accordingly
    deid = MyRegex.Replace(deid, New MatchEvaluator(Function(m As Match)
                                                        Return m.Groups("pre").Value &
                                                            "******/*****" &
                                                            m.Groups("post").Value &
                                                            New String("."c, 5 - m.Groups("pkid").Value.Length) &
                                                            "******"
                                                    End Function))

我运行通过测试数据,这是我得到的:

-----Input------------------------------------------------
1 01SMITH/CH..1.A E2T......AAABBB
2 01MTC..1.A ..............CCCDDD
3 01GRIFFIN/JOHN..1.A E2...EEEFFF
4 01EL/MARY..1.Z E2XT......GGGHHH
5 02BUBBA/BILLY..2.A E2....IIIJJJ
6 01HILL/THOR..1.A E2WW....KKKLLL
-----Output-----------------------------------------------
1 01******/*****..1.A E2T..******
2 01******/*****..1.A .....******
3 01******/*****..1.A E2...******
4 01******/*****..1.Z E2XT.******
5 02******/*****..2.A E2...******
6 01******/*****..1.A E2WW.******
----------------------------------------------------------

也许,可以有更好的方法,但可以用 your regex and Regex.Replace using a MatchEvaluator 来实现你想要的。

evaluator
Type: System.Text.RegularExpressions.MatchEvaluator
A custom method that examines each match and returns either the original matched string or a replacement string.

重点是获取第3组和第8组的长度,重复*同样的次数。要添加正斜杠,我们可以通过将第 3 组的长度除以 2 来找到中间点。StrDup 是一个方便的函数,它 "multiplies" 字符串指定的次数。

这是一个VB.NET代码:

Dim Input As String = "1 01SMITH/CH..1.A E2T......AAABBB" & Environment.NewLine & "2 01MTC..1.A ..............CCCDDD" & Environment.NewLine & "3 01GRIFFIN/JOHN..1.A E2...EEEFFF" & Environment.NewLine & "4 01EL/MARY..1.Z E2XT......GGGHHH" & Environment.NewLine & "5 02BUBBA/BILLY..2.A E2....IIIJJJ" & Environment.NewLine & "6 01HILL/THOR..1.A E2WW....KKKLLL"
Dim MyRegex As Regex = New Regex("(?<pre>^\s{0,2}(\d{1,3})\s(\d\d))(.+?)(?<post>\.\.(\d{1,3})\." + "(\w)\s((\w+?|\.\.)))(?<dots>\.+)(\w{6})", RegexOptions.IgnoreCase Or RegexOptions.Multiline)
Dim result As String = MyRegex.Replace(Input, New MatchEvaluator(Function(m As Match)
                                    Return m.Groups("pre").Value &
                                    StrDup(m.Groups(3).Value.Length, "*").Insert(m.Groups(3).Value.Length / 2, "/") &
                                    m.Groups("post").Value &
                                    m.Groups("dots").Value &
                                    StrDup(m.Groups(8).Value.Length, "*")
                              End Function))
Console.WriteLine(result)

结果:

1 01****/****..1.A E2T......******
2 01**/*..1.A ..............******
3 01******/******..1.A E2...******
4 01****/***..1.Z E2XT......******
5 02******/*****..2.A E2....******
6 01****/*****..1.A E2WW....******