查找 2 个特定数字后包含 6 位数字的行

查找 2 个特定数字后包含 6 位数字的行

我需要创建一个正则表达式来显示以下行包含94 或 95 或 96 或 97 或 99。

grep -P '(94|95|96|97|99)'

这 2 位数字后面很可能有 6 个或更多数字,但它们之间可能有空格,所以我必须删除它们。

sed 's/\(.\) /\1/g'

然后我必须删除任何提及 357、00357 或 +357 的内容

sed 's/\(357\|00357\|+357\)//g'

最后要做的就是确保每行只有 6 位数字上面提到的最初的2。所以每一行应该包含总共 8 位数字,从 94 或 95 或 96 或 97 或 99 开始。如果数字多于或少于 8 个,那么该行对我来说就没用。

如何检查每一行是否包含以 94 或 95 或 96 或 97 或 99 开头的数字,并且后面仅剩 6 位数字,并仅显示这些行?

输入可能是这样的

2020-11-03  13:00   2020-11-03  14:00   99 123456
2020-11-03  13:00   2020-11-03  14:00   9412 3456
2020-11-03  13:00   2020-11-03  14:00   95123456
2020-11-03  13:00   2020-11-03  14:00   456345 3453543654567
2020-11-03  13:00   2020-11-03  14:00   +357678423683
2020-11-03  13:00   2020-11-03  14:00   00357584903
2020-11-03  13:00   2020-11-03  14:00   +35 799 1276 45
2020-11-03  13:30   2020-11-03  14:30   97123456

和预期的输出是这样的

2020-11-03  13:00   2020-11-03  14:00   99123456
2020-11-03  13:00   2020-11-03  14:00   94123456
2020-11-03  13:00   2020-11-03  14:00   95123456
2020-11-03  13:00   2020-11-03  14:00   99127645
2020-11-03  13:30   2020-11-03  14:30   97123456

答案1

使用perl,您可以执行以下操作:

perl -lne 'if (/\t\K(?:(?:\+|00)? ?3 ?5 ?7 ?)?(9[4-9]( ?\d){6})\s*$/) {
           s{}{$1 =~ s/ //gr}e; print}' < file

sed与(假设具有扩展正则表达式支持的实现)相同-E

eval "$(printf 'NL="\n" TAB="\t"')"
LC_ALL=C sed -E "
  /$TAB((00|\+)?3 ?5 ?7 ?)?(9[4-9]( ?[0-9]){6})[[:space:]]*\$/!d
  s//$TAB\\$NL\3/;  # separate prefix and 8 digits
  h;                # save a copy
  s/.*\n//;         # extract 8 digits
  s/ //g;           # remove spaces among digits
  G;                # append saved copy and keep prefix and trimmed digits:
  s/(.*)\n(.*)\n.*/\2\1/" < file

在这里,我们假设字段像示例输入中那样以 TAB 分隔,并且仅在遵循 TAB 时才查找该数字,以避免像 中那样出现误报+1 996 123456

答案2

用 awk

awk '{
    match($0,/^([^[:space:]]+[[:space:]]+){4}/)
    last_part = substr($0,RLENGTH+1)

    gsub(/[[:space:]]/,"",last_part)
    gsub(/^(+|00)357/,"",last_part)

    if (last_part ~ /^9[45679]/ && length(last_part) == 8) {
        printf "%s%s\n", substr($0,1,RLENGTH), last_part
    }
}' file

输出:

2020-11-03  13:00   2020-11-03  14:00   99123456
2020-11-03  13:00   2020-11-03  14:00   94123456
2020-11-03  13:00   2020-11-03  14:00   95123456
2020-11-03  13:00   2020-11-03  14:00   99127645
2020-11-03  13:30   2020-11-03  14:30   97123456

解释:

  • match()将前 4 个字段与其后面的空格匹配,之后,内置变量RLENGTH保存第一部分的结尾。我们可以拆分为字段,但我不喜欢在这种情况下拆分,以保持初始对齐并轻松匹配开始的数字区域的索引,现在是RLENGTH+1

  • 首先gsub()删除数字区域中的所有空格。为了方便起见,我们分两步执行此操作(为了不担心任何+35 7其他问题)

  • 第二步gsub()查找前缀(+35700357357)并将其删除。

  • 最后,如果数字区域以我们想要的前缀开头长度为8个字符,printf换行。

参考:GNU awk 字符串函数

答案3

我会匹配:

  Space
  9
  5 through 9
  0 or 1 Space
  6 digits
  a non-digit


grep -E ' 9[5-9] ?[0-9]{6}[^0-9]' file

相关内容