将位置替换为文件中的另一个位置

将位置替换为文件中的另一个位置

我有一个具有固定记录长度的平面文件(~2500)

H20190105                         
D0012345APPLE INC      100001072010
D0008912SAMSUNG        450023082005
T0001245678                       
  • 位置 2-8 A/C#(左侧用零填充)
  • 第9-23位账户名称(右侧补空格)
  • 位置 24 其余字段

我需要通过从 A/C# 中删除前导零,将文件中的帐户名称字段(位置 9-23)屏蔽为 ACCT_A/C#

期望的结果如下

H20190105
D0012345ACCT_12345     100001072010
D0008912ACCT_8912      450023082005
T0001245678

我使用了下面的命令,但无法从 A/C# 中删除前导零。

awk '/^D/{$0=substr($0,1,8)"ACCT_"substr($0,2,7)"  "substr($0,24,length($0))} 1' FILE.TXT > OUT.TXT

使用int(substr($0,2,7))修剪零可以更改下一个字段位置。

任何人都可以帮助获得想要的结果吗?

答案1

相当短的awk一句话:

$ awk '/^D/ { nr = substr($0,2,7); $0 = sprintf("D%07dACCT_%-10d%s", nr, nr, substr($0,24)) } { print }' file
H20190105
D0012345ACCT_12345     100001072010
D0008912ACCT_8912      450023082005
T0001245678

该代码将通过第一个位置中awk是否存在 a 来检测需要修改的行。D

sprintf()新行由 after 的零填充数字、后跟相同数字的D字符串(现在不是零填充)以及最后该行位置 24 中和位置 24 之后的内容构成。ACCT_

打印所有行(如上所述修改或根本不修改)。

答案2

$ perl -pe 's/^(D)(.{7})(.{12})/sprintf("%s%s%s%-7s",$1,$2,"ACCT_",$2+0)/e' input.txt 
H20190105                         
D0012345ACCT_12345     100001072010
D0008912ACCT_8912      450023082005
T0001245678                       

这使用了 perl 的运算e符修饰符s/LHS/RHS/,以便将 RHS 作为 perl 代码执行。隐$2+0式将 $2 从零填充字符串转换为数字,这会自动删除所有前导零。该sprintf()格式确保输出行具有与输入完全相同的字段长度。


或者,修复你的awk一句台词:

$ awk '/^D/{$0=substr($0,1,8)"ACCT_"sprintf("%-7s",substr($0,2,7)+0)"  "substr($0,24,length($0))} 1' input.txt 
H20190105                         
D0012345ACCT_12345    100001072010
D0008912ACCT_8912     450023082005
T0001245678                       

awk也有 sprintf 。 IMO 这比 perl 版本更难阅读和理解。 YMMV。

另一个awk版本,类似于perl版本:

$ awk '
   /^D/ {
     ac=sprintf("%-7s",substr($0,2,7)+0);
     $0=gensub("^(D)(.{7})(.{12})","\\1\\2ACCT_"ac,1)
   }
   1' input.txt 
H20190105                         
D0012345ACCT_12345     100001072010
D0008912ACCT_8912      450023082005
T0001245678                       

如果您不需要删除零填充,可以通过以下方式完成sed

$ sed -E -e 's/^(D)(.{7})(.{12})/\1\2ACCT_\2/' input.txt 
H20190105                         
D0012345ACCT_0012345   100001072010
D0008912ACCT_0008912   450023082005
T0001245678                       

答案3

$ awk 'NF>1{$0=sprintf("%sACCT_%-11d%s", substr($0,1,8), substr($0,2,7), substr($0,24))} 1' file
H20190105
D0012345ACCT_12345      100001072010
D0008912ACCT_8912       450023082005
T0001245678

相关内容