我需要创建一个正则表达式来显示以下行包含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()
查找前缀(+357
、00357
或357
)并将其删除。最后,如果数字区域以我们想要的前缀开头和长度为8个字符,
printf
换行。
答案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