如何替换文件第二列末四位及第三列日期前末四位数字并保留格式?
问题:保留原格式替换指定数字段
原文件内容
2300 10 1112221234 111222123420231121PPPPD10+0000000850 ESIM 10 3334446789 333444678920231121PPPPD11+0000000950 RSIM 23
期望处理结果
2300 10 1112222345 111222234520231121PPPPD10+0000000850 ESIM 10 3334447890 333444789020231121PPPPD11+0000000950 RSIM 23
错误尝试及问题
使用以下awk脚本时,虽能替换目标数字,但会压缩字段间空格,还会丢失第三列第11位之后的内容:
2300 10 1112222345 1112222345 ESIM 10 3334447890 3334447890 RSIM 23 awk ' BEGIN { FS=OFS=" " } {if(length($2)>9 && length($3)>9) {$2 = substr($2,-10) $3 = substr($3,1,10) for (i=2;i<=3;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' filename
问题根源:设置FS=OFS=" "会将所有连续空格视为单个分隔符,输出时用单个空格分隔字段,破坏原格式;同时手动截断了第三列的后续内容。
正确解决方案
采用不拆分字段的方式,直接对整行进行正则匹配和替换,完整保留原格式:
/^10/ { # 处理第二列的10位数字:前6位保留,后四位每位加1取模10 match($0, /^10[[:space:]]+([0-9]{6})([0-9]{4})/, col2_parts) new_suffix2 = "" for(i=1; i<=4; i++) { new_suffix2 = new_suffix2 (substr(col2_parts[2], i, 1) + 1) % 10 } new_col2 = col2_parts[1] new_suffix2 # 处理第三列:前10位的后四位每位加1取模10,保留后续所有内容 match($0, /([0-9]{6})([0-9]{4})(20231121.*)$/, col3_parts) new_suffix3 = "" for(i=1; i<=4; i++) { new_suffix3 = new_suffix3 (substr(col3_parts[2], i, 1) + 1) % 10 } new_col3 = col3_parts[1] new_suffix3 col3_parts[3] # 替换原行对应部分,保留空格格式 sub(/^10[[:space:]]+[0-9]{10}/, "10 " new_col2) sub(/[0-9]{10}(20231121.*)$/, new_col3) } # 输出所有行(含未处理的行) 1
脚本说明
- 仅处理以
10开头的行,其他行直接输出 - 用
match函数匹配目标数字段,拆分出需保留的前缀和需修改的后四位 - 对后四位数字逐个加1并取模10,生成新后缀
- 用
sub函数替换原行对应内容,手动保留第二列前的空格格式(与原文件一致的10) - 第三列替换时完整保留日期及后续内容,无信息丢失
运行结果
执行上述脚本后,输出与期望结果完全一致,同时保留了原文件的空格格式。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

