将大型机 SORT 转换为 Shell 脚本
Convert Mainframe SORT to Shell Script
有没有简单的方法可以将 JCL SORT 转换为 Shell 脚本?
这是 JCL 排序:
OPTION ZDPRINT
SORT FIELDS=(15,1,CH,A)
SUM FIELDS=(16,8,25,8,34,8,43,8,52,8,61,8),FORMAT=ZD
OUTREC BUILD=(14X,15,54,13X)
只有长度为 54 的字节 15 与输入数据相关,这是求和的键和源值。输入中的其他字节并不重要。
假设数据是可打印的。
数据按单字节键排序,对于六个数字中的每一个,具有相同键的记录的每个值分别求和。每个键写入一条记录,其中包含 first 记录中的求和值和其他数据(中间和末尾的那些字节)。排序是 "unstable"(这意味着呈现给求和的记录的顺序不能从一次执行到下一次执行重现)因此字节值在理论上应该在所有记录上相同,或者不相关。
每个键的输出显示为包含 14 个空格 (14X) 的记录,然后是从位置 15 开始的 54 个字节(这是单字节键),然后是 13 个空格 (13X)。数字应右对齐并左填零[OP 确认并修改示例数据和预期输出]。
假设和只包含正数并且不会被签名,并且对于任何小于 999999990 的数字,任何未使用的位置都会有前导零(数字是字符,右对齐和左零-填充)。
假设单字节密钥只会是字母。
数据已经从 EBCDIC 转换为 ASCII。
示例输入:
00000000000000A11111111A11111111A11111111A11111111A11111111A111111110000000000000
00000000000000B22222222A22222222A22222222A22222222A22222222A222222220000000000000
00000000000000C33333333A33333333A33333333A33333333A33333333A333333330000000000000
00000000000000A44444444B44444444B44444444B44444444B44444444B444444440000000000000
预期输出:
A55555555A55555555A55555555A55555555A55555555A55555555
B22222222A22222222A22222222A22222222A22222222A22222222
C33333333A33333333A33333333A33333333A33333333A33333333
(14 个前置空格和 13 个尾随空格)
预期交易量:一万
好的,我试过了
1) 从文件中提取重复键并将其存储在重复文件中。
awk '{k=substr([=10=],1,15);a[k]++}END{for(i in a)if(a[i]>1)print i}' sample > duplicates
或
awk '{k=substr([=11=],1,15);print k}' sample | sort | uniq -c | awk '>1{print }' > duplicates
2) 对于重复项,进行计算并创建具有指定格式的新文件
while read line
do
grep ^$line sample | awk -F[A-Z] -v key=$line '{for(i=2;i<=7;i++)f[i]=f[i]+$i}END{printf("%14s"," ");for(i=2;i<=7;i++){printf("%s%.8s",substr(key,15,1),f[i]);if(i==7)printf("%13s\n"," ")}}' > newfile
done < duplicates
3) 对于唯一的,格式化并附加到新文件
grep -v -f duplicates sample | sed 's/0/ /g' >> newfile ## gives error if 0 is within data instead of start and end in a row.
或
grep -v -f duplicates sample | awk '{printf("%14s%s%13s\n"," ",substr([=14=],15,54)," ")}' >> newfile
如果您有任何疑问,请告诉我。
我想出了答案:
awk -v FIELDWIDTHS="14 1 8 1 8 1 8 1 8 1 8 1 8 13" \
'{if(!( in a)) {a[]=; c[]=; e[]=; g[]=; i[]=; k[]=} \
b[]+=; d[]+=; f[]+=; h[]+=; j[]+=; l[]+=;} END \
{for(id in a) printf("%14s%s%s%s%s%s%s%s%s%s%s%s%s%13s\n","",a[id],b[id],c[id],d[id],e[id],f[id],g[id],h[id],i[id],j[id],k[id],l[id],"");}' input
解释:
1) 拆分字符串
awk -v FIELDWIDTHS="14 1 8 1 8 1 8 1 8 1 8 1 8 13"
2) 设$2为key,$4, $6, $8, $10, $12只会第一次设置值
{if(!( in a)) {a[]=; c[]=; e[]=; g[]=; i[]=; k[]=}
3) 其他的再总结
b[]+=; d[]+=; f[]+=; h[]+=; j[]+=; l[]+=;} END
4) 为每个键打印
{for(id in a) printf("%14s%s%s%s%s%s%s%s%s%s%s%s%s%13s\n","",a[id],b[id],c[id],d[id],e[id],f[id],g[id],h[id],i[id],j[id],k[id],l[id],"");}
有没有简单的方法可以将 JCL SORT 转换为 Shell 脚本?
这是 JCL 排序:
OPTION ZDPRINT
SORT FIELDS=(15,1,CH,A)
SUM FIELDS=(16,8,25,8,34,8,43,8,52,8,61,8),FORMAT=ZD
OUTREC BUILD=(14X,15,54,13X)
只有长度为 54 的字节 15 与输入数据相关,这是求和的键和源值。输入中的其他字节并不重要。
假设数据是可打印的。
数据按单字节键排序,对于六个数字中的每一个,具有相同键的记录的每个值分别求和。每个键写入一条记录,其中包含 first 记录中的求和值和其他数据(中间和末尾的那些字节)。排序是 "unstable"(这意味着呈现给求和的记录的顺序不能从一次执行到下一次执行重现)因此字节值在理论上应该在所有记录上相同,或者不相关。
每个键的输出显示为包含 14 个空格 (14X) 的记录,然后是从位置 15 开始的 54 个字节(这是单字节键),然后是 13 个空格 (13X)。数字应右对齐并左填零[OP 确认并修改示例数据和预期输出]。
假设和只包含正数并且不会被签名,并且对于任何小于 999999990 的数字,任何未使用的位置都会有前导零(数字是字符,右对齐和左零-填充)。
假设单字节密钥只会是字母。
数据已经从 EBCDIC 转换为 ASCII。
示例输入:
00000000000000A11111111A11111111A11111111A11111111A11111111A111111110000000000000
00000000000000B22222222A22222222A22222222A22222222A22222222A222222220000000000000
00000000000000C33333333A33333333A33333333A33333333A33333333A333333330000000000000
00000000000000A44444444B44444444B44444444B44444444B44444444B444444440000000000000
预期输出:
A55555555A55555555A55555555A55555555A55555555A55555555
B22222222A22222222A22222222A22222222A22222222A22222222
C33333333A33333333A33333333A33333333A33333333A33333333
(14 个前置空格和 13 个尾随空格)
预期交易量:一万
好的,我试过了
1) 从文件中提取重复键并将其存储在重复文件中。
awk '{k=substr([=10=],1,15);a[k]++}END{for(i in a)if(a[i]>1)print i}' sample > duplicates
或
awk '{k=substr([=11=],1,15);print k}' sample | sort | uniq -c | awk '>1{print }' > duplicates
2) 对于重复项,进行计算并创建具有指定格式的新文件
while read line
do
grep ^$line sample | awk -F[A-Z] -v key=$line '{for(i=2;i<=7;i++)f[i]=f[i]+$i}END{printf("%14s"," ");for(i=2;i<=7;i++){printf("%s%.8s",substr(key,15,1),f[i]);if(i==7)printf("%13s\n"," ")}}' > newfile
done < duplicates
3) 对于唯一的,格式化并附加到新文件
grep -v -f duplicates sample | sed 's/0/ /g' >> newfile ## gives error if 0 is within data instead of start and end in a row.
或
grep -v -f duplicates sample | awk '{printf("%14s%s%13s\n"," ",substr([=14=],15,54)," ")}' >> newfile
如果您有任何疑问,请告诉我。
我想出了答案:
awk -v FIELDWIDTHS="14 1 8 1 8 1 8 1 8 1 8 1 8 13" \
'{if(!( in a)) {a[]=; c[]=; e[]=; g[]=; i[]=; k[]=} \
b[]+=; d[]+=; f[]+=; h[]+=; j[]+=; l[]+=;} END \
{for(id in a) printf("%14s%s%s%s%s%s%s%s%s%s%s%s%s%13s\n","",a[id],b[id],c[id],d[id],e[id],f[id],g[id],h[id],i[id],j[id],k[id],l[id],"");}' input
解释:
1) 拆分字符串
awk -v FIELDWIDTHS="14 1 8 1 8 1 8 1 8 1 8 1 8 13"
2) 设$2为key,$4, $6, $8, $10, $12只会第一次设置值
{if(!( in a)) {a[]=; c[]=; e[]=; g[]=; i[]=; k[]=}
3) 其他的再总结
b[]+=; d[]+=; f[]+=; h[]+=; j[]+=; l[]+=;} END
4) 为每个键打印
{for(id in a) printf("%14s%s%s%s%s%s%s%s%s%s%s%s%s%13s\n","",a[id],b[id],c[id],d[id],e[id],f[id],g[id],h[id],i[id],j[id],k[id],l[id],"");}