提问人:Sam 提问时间:11/15/2023 最后编辑:markp-fusoSam 更新时间:11/15/2023 访问量:114
用添加 1 位数字替换最后 4 位数字(不包括 0x)
Replace last 4 digits by adding 1 digit (excluding 0x)
问:
我有以下文件(test.txt),我想更改逻辑如下:
0 becomes 1
1 becomes 2
2 becomes 3
3 becomes 4
4 becomes 5
5 becomes 6
6 becomes 7
7 becomes 8
8 becomes 9
9 becomes 0
$ cat test.txt
69|1074330570|1,sip:+121345633210x3Bverstat=TN-Validation-Passed|tel:+12134565534|0
69|1077822111|2,;tel:+12223120011~sip:[email protected];|sip:[email protected]|0
我想更改最后 4 位数字,但是当 x 紧挨着 0x 时,则 0 不计算在内。 例如: 在第一行“+121345633210x”中,最后 4 个是 3321。 在第二行中,“+12223120011”,最后 4 个是 0011,“+12223120051”,最后 4 个是 0051 输出应如下所示:
69|1074330570|1,sip:+121345644320x3Bverstat=TN-Validation-Passed|tel:+12134566645|0
69|1077822111|2,;tel:+12223121122~sip:[email protected];|sip:[email protected]|0
它需要排除“+1”,然后计算“10”位,我想在其中替换第三列和第四列的最后 4 位。
121345633210 becomes 121345644320 / 12134565534 becomes 12134566645
12223120011 becomes 12223121122 / 12223120051 becomes 12223121162 / 13123120022 becomes 13123121133
当列只是一个数字时,我使用了以下逻辑。但在这种情况下,它还有其他东西,所以下面的逻辑不起作用,但通过添加 1 位数字来转换数字是正确的。
awk -F"|" -v OFS="|" '
NR>0 {
for (i=3;i<=4;i++) {
str = substr($i, 1, length($i) - 4)
for (j = length($i) - 3; j <= length($i); j++) {
str = str (substr($i, j, 1) + 1) % 10
}
$i = str
}
}
1'
答:
3赞
anubhava
11/15/2023
#1
使用 ,您可以执行以下操作:gnu-awk
awk '
function repl(s, i, r, ch) {
for (i=1; i<=length(s); ++i) {
ch = substr(s,i,1)
r = r (ch == 9 ? 0 : ch+1)
}
return r
}
BEGIN {FS=OFS="+"}
{
for (j=2; j<=NF; ++j) {
if (match($j, /^([0-9]+)([0-9]{4})(0x|[^x0-9]|$)(.*)/, a))
$j = a[1] repl(a[2]) a[3] a[4]
}
} 1' file
69|1074330570|1,sip:+121345644320x3Bverstat=TN-Validation-Passed|tel:+12134566645|0
67|1077822111|2,;tel:+12223121122~sip:[email protected];|sip:[email protected]|0
3赞
markp-fuso
11/15/2023
#2
假设:
- A 仅出现在第 3/4 个字段中,然后仅显示在电话号码的前面
+
一种方法:awk
awk '
BEGIN { FS=OFS="+" } # split input on "+"
{ for (i=2; i<=NF; i++) { # loop through fields that start with a phone number
oldfld = $i # save current field
$i = "" # initialize new field
d1 = substr(oldfld,1,1) # get 1st digit
len = (d1 == 1 ? 7 : 6) # determine length of phone prefix
$i = substr(oldfld,1,len) # save everything up to the phone prefix
for (j=(len+1); j<=(len+4); j++) { # loop through last 4 digits of phone number
x = substr(oldfld,j,1) # get current digit
$i = $i (x==9 ? 0 : x+1) # increment and add to new field
}
$i = $i substr(oldfld,len+4+1) # save rest of old field
}
}
1 # print current line
' test.txt
这将生成:
69|1074330570|1,sip:+121345644320x3Bverstat=TN-Validation-Passed|tel:+12134566645|0
69|1077822111|2,;tel:+12223121122~sip:[email protected];|sip:[email protected]|0
3赞
Ed Morton
11/15/2023
#3
使用 GNU awk 作为第 3 个参数来匹配():
$ awk '{
head = ""
while ( match($0,/([^+]+\+[0-9]{7})([0-9]{4})/,a) ) {
digs = ""
for ( i=1; i<=4; i++ ) {
digs = digs ((substr(a[2],i,1) + 1) % 10)
}
head = head a[1] digs
$0 = substr($0,RSTART+RLENGTH)
}
print head $0
}' test.txt
69|1074330570|1,sip:+121345644320x3Bverstat=TN-Validation-Passed|tel:+12134566645|0
69|1077822111|2,;tel:+12223121122~sip:[email protected];|sip:[email protected]|0
这会产生预期的输出,而无需仅测试第 3 或第 4 个字段,也没有测试,因为除了 3 或 4 之外,字段中没有与目标正则表达式匹配的字符串,尽管您说忽略后跟 ,但实际上您只是总是更改前 11 位数字,而后面的任何数字都是第 12 位数字。0x
0
x
0
x
您可以使用任何 POSIX awk 执行相同的操作:
awk '{
head = ""
while ( match($0,/\+[0-9]{11}/) ) {
digs = ""
for ( i=1; i<=4; i++ ) {
digs = digs ((substr($0,RSTART+RLENGTH-5+i,1) + 1) % 10)
}
head = head substr($0,1,RSTART+RLENGTH-5) digs
$0 = substr($0,RSTART+RLENGTH)
}
print head $0
}' test.txt
评论
+
str = substr(...)
print $i,str
$i
str