我有一个具有固定记录长度的平面文件(~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