按字段长度

时间:2016-11-12 09:40:38

标签: mainframe dfsort

我想编写一个带有需求的排序JCL,我想对变量记录长度文件进行排序

输入文件:

Mark aaaaaaa
Amy bbbbbb
Paula ccccccccccc

按升序排序的空格前的字段长度排序。这是根据他们的长度排序第一个col / word Mark,Amy等的长度。

第二个就像在降序空格后对字段进行排序,但是如果字段中的任何元音应该始终是第一个,那么其余的数据。 来到第二部分,这里就像空格或aaaaa,bbbbb和ccccc之后的字段我们需要按降序排序(按字母顺序),但是我们还需要检查字段是否为vovel,如果有任何vovel那么该字段将始终是顶部,所以预期的输出将是: 考虑上面的输入文件输出文件将是:

Mark aaaaaaaa
宝拉cccccc
艾米bbbbbb

现在这里的声音就像第一个包含aaaa的记录在顶部而休息数据按降序排序。我想实现这个目标。

1 个答案:

答案 0 :(得分:1)

你问的问题根本不是一件简单的事情: - )

虽然DFSORT具有许多内在功​​能,但是找不到一系列非空格字符的长度。

所以你必须自己动手。

尽管使用固定长度记录(不同技术)也可以执行任务,但使用可变长度记录更容易。

因为字段也是可变长度的,所以你需要PARSE来分隔字段。对于可变长度或可变位置的字段,PARSE通常是答案。

PARSE创建固定长度的解析字段,因此您必须知道文本的最大长度。在这个例子中,为每个选择了30个。

解决方案将逐个开发,因为您需要确保对它的理解。这些作品以"独立呈现为#34;你可以运行的代码,看看会发生什么:

选项复制

  INREC IFTHEN=(WHEN=INIT, 
                 PARSE=(%01=(ENDBEFR=C' ',
                             FIXLEN=30), 
                        %02=(FIXLEN=30))),


        IFTHEN=(WHEN=INIT, 
                 BUILD=(1,4,%01,%02)) 

如果你运行它,你将得到这个输出:

MARK                          AAAAAAA                       
AMY                           BBBBBB                        
PAULA                         CCCCCCCCCCC                   

INREC在SORT之前运行,因此要在SORT之前对数据进行任何更改,请使用INREC。 OUTREC在SORT之后运行,在OUTREC之后运行OUTFIL。

目前,BUILD只是为了表明PARSEd字段包含你想要的输出(不要担心这种情况,如果你使用混合大小写的话就是这样)。

WHEN = INIT表示"在以下IFTHEN语句(如果有)"之前为每条记录执行此操作。您可以使用多个WHEN = INIT,并且必须使用某种类型的多个IFTHEN来分阶段转换数据。

BUILD中的1,4用于记录描述符字(RDW),每个可变长度记录都有,并且在SORT中创建可变长度当前记录时始终是必需的,但我们将使用它在这里也是为了另一个目的。

下一阶段是"延伸"记录,因为我们需要两个字段来SORT。对于可变长度记录,您可以在前面扩展"。一般来说:

BUILD=(1,4,extensionstuff,5)

这是当前记录的新版本,首先是来自旧的当前记录的RDW,然后"做一些事情"创建扩展,然后从位置5(可变长度记录的第一个数据字节)复制到记录的末尾。

虽然RDW被"复制",但当时RDW的值是无关紧要的,因为它将为BUILD计算。它必须是一个RDW开始,除了实际的RDW之外,你不能把它放在那里。

需要的另一个组件是扩展SORT键的记录。我们需要第一个字段的长度,我们需要一个"标记"是否早期排序"对于包含元音的第二个字段。对于长度,具有双字节二进制值将是方便的。现在,我们只是为事物保留字节:

OPTION COPY
INREC BUILD=(1,4,2X,2X,X,5)

2X是两个空白,X是一个空白,所以总共五个空白。它本来可以写成5X,并且在最终的代码中最好的方式,但现在它更清晰。运行它,你会看到你的记录前缀为五个空格。

有两项任务。第一个字段的长度,以及第二个字段是否包含元音。

第一项任务的关键是用“#34; nothing"”替换PARSEd字段中的空格。这将导致记录被替换为每个空白一个缩短。保存原始当前记录的长度,并使用当前记录的长度和固定长度(30)计算显示数据的长度。

第二项任务的关键是采用类似的技术。这次,改变第二个PARSEd字段,使得a,e,i,o,u被" nothing"替换。然后,如果长度与原始长度相同,则没有元音。

FINDREP看起来像这样:

     IFTHEN=(WHEN=INIT, 
              FINDREP=(IN=C' ', 
                       OUT=C'', 
                       STARTPOS=n1, 
                       ENDPOS=n2)),

您需要元音的变体:

     IFTHEN=(WHEN=INIT, 
              FINDREP=(IN=(C'A',C'E',C'I',C'O',C'U'), 
                       OUT=C'', 
                       STARTPOS=n1, 
                       ENDPOS=n2)),

运行:

  OPTION COPY 

  INREC IFTHEN=(WHEN=INIT, 
                 PARSE=(%01=(ENDBEFR=C' ',
                             FIXLEN=30), 
                        %02=(FIXLEN=30))),

        IFTHEN=(WHEN=INIT, 
                 BUILD=(1,4,2X,X,%02)), 

        IFTHEN=(WHEN=INIT, 
                 OVERLAY=(5:1,2)), 

        IFTHEN=(WHEN=INIT, 
                  FINDREP=(IN=(C'A', 
                               C'E', 
                               C'I', 
                               C'O', 
                               C'U'), 
                           OUT=C'', 
                           STARTPOS=8, 
                           ENDPOS=38)), 

        IFTHEN=(WHEN=(1,4,BI,EQ,5,2,BI), 
                OVERLAY=(7:C'N')) 

如果你运行它,你会看到标志(第三个数据位置)现在是空格(对于元音存在)或" N"。不要担心所有的" A"已经消失了,它们仍然隐藏在%02中。

OVERLAY可以在不创建新的替换记录的情况下对当前记录进行更改(这是BUILD所做的)。在创建新的当前记录长度之后,您将看到下面使用的OVERLAY获取新的记录长度(BUILD将从RDW获得原始记录长度。)

其他任务的类似过程。

我已经包含了一些额外的测试数据,并对您的SORT订单做了进一步的假设。这里有完整的,带注释的(注释可以保留,它们不会影响处理),代码:

* PARSE CURRENT INPUT TO GET TWO FIELDS, HELD SEPARATELY FROM THE RECORD. 
* 
  INREC IFTHEN=(WHEN=INIT, 
                 PARSE=(%01=(ENDBEFR=C' ', 
                             FIXLEN=30), 
                        %02=(FIXLEN=30))), 

* MAKE A NEW CURRENT RECORD, RDW FROM EXISTING RECORD, THREE EXTENSIONS, AND 
* A COPY OF THE FIRST PARSED FIELD. 
* 
        IFTHEN=(WHEN=INIT, 
                BUILD=(1,4, 
                       2X, 
                       2X, 
                       X, 
                       %01)), 

* STORE THE LENGTH OF THE NEW CURRENT RECORD ON THE CURRENT RECORD. 
* 
        IFTHEN=(WHEN=INIT, 
                 OVERLAY=(5: 
                            1,2)), 

* REPLACE BLANKS WITH "NOTHING" WITHIN THE COPY OF THE PARSED FIELD. THIS WILL 
* AUTOMATICALLY ADJUST THE RDW ON THE CURRENT RECORD. 
* 
        IFTHEN=(WHEN=INIT, 
                  FINDREP=(IN=C' ', 
                           OUT=C'', 
                           STARTPOS=10, 
                           ENDPOS=40)), 

* CALCULATE THE LENGTH OF THE NON-BLANKS IN THE FIELD, BY SUBTRACTING PREVIOUS 
* STORED RECORD-LENGTH FROM CURRENT RECORD-LENGTH (FIRST TWO BYTES, BINARY, OF 
* RDW) AND ADDING 30 (LENGTH OF PARSED FIELD). 
* 
        IFTHEN=(WHEN=INIT, 
                OVERLAY=(5: 
                           1,2,BI, 
                           SUB, 
                            5,2,BI, 
                           ADD, 
                            +30, 
                           TO=BI, 
                           LENGTH=2)), 

* MAKE A NEW CURRENT RECORD, COPYING RDW AND THE VALUE CALCULATED ABOVE, BLANKS
* (COULD BE COPIED) AND THEN THE SECOND PARSED FIELD. 
* 
        IFTHEN=(WHEN=INIT, 
                 BUILD=(1,4, 
                        5,2, 
                        2X, 
                        X, 
                        %02)), 

* AGAIN SAVE THE LENGTH OF THE NEW CURRENT RECORD. 
* 
        IFTHEN=(WHEN=INIT, 
                 OVERLAY=(7: 
                            1,2)), 

* CHANGE ALL VOWELS TO "NOTHING". THIS WILL AUTOMATICALLY ADJUST THE RDW. FOR
* MIXED-CASE JUST EXTEND THE IN TO INCLUDE LOWER-CASE VOWELS AS WELL. 
* 
        IFTHEN=(WHEN=INIT, 
                 FINDREP=(IN=(C'A', 
                              C'E', 
                              C'I', 
                              C'O', 
                              C'U'), 
                          OUT=C'', 
                          STARTPOS=10, 
                          ENDPOS=40)), 

* CALCULATE NUMBER OF VOWELS. 
* 
        IFTHEN=(WHEN=INIT, 
                 OVERLAY=(7: 
                            7,2,BI, 
                           SUB, 
                            1,2,BI, 
                           TO=BI, 
                           LENGTH=2)), 

* MAKE A NEW CURRENT RECORD TO BE SORTED, WITH BOTH PARSED FIELDS. 
* 
        IFTHEN=(WHEN=INIT, 
                 BUILD=(1,4, 
                        5,2, 
                        7,2, 
                        9,1, 
                        %01, 
                        %02)), 

* SET THE FLAG TO "OUTSORT" THOSE RECORDS WITH A VOWEL IN THE SECOND FIELD. 
* 
        IFTHEN=(WHEN=(7,2,BI,EQ,0), 
                 OVERLAY=(9: 
                            C'N')) 

* SORT ON "OUTSORT FLAG", LENGTH OF NAME (DESCENDING), NAME, 2ND FIELD. 
  SORT FIELDS=(9,1,CH,A, 
               5,2,CH,D, 
               10,30,CH,A, 
               40,30,CH,A) 

* FIELDS NEEDED TO BE IN FIXED POSITION FOR SORT, AND EXTENSION FIELDS NO 
* LONGER NEEDED. ALSO REMOVE BLANKS FROM THE TWO FIELDS, KEEPING A SEPARATOR   
* BETWEEN THEM. THIS COULD INSTEAD BE DONE ON THE OUTFIL. 
* 
  OUTREC BUILD=(1,4, 
                10,60, 
                 SQZ=(SHIFT=LEFT, 
                      MID=C' ')) 

* CURRENTLY THE VARIABLE-LENGTH RECORDS ARE ALL THE SAME LENGTH (69 BYTES) SO 
* REMOVE TRAILING BLANKS. 
* 
  OUTFIL VLTRIM=C' ' 

广泛的测试数据:

MARK AAAAAAA 
AMY BBBBBB 
PAULA CCCCCCCCCCC
PAULA BDDDDDDDDDD
IK JJJJJJJJJJO 

您还可以看到代码的工作原理"一次删除一行"从代码的末尾开始,这样你就可以看到转换如何到达那一点,或者通过运行代码从代码的开头一次增加一行。

您和您的同事了解代码非常重要。

有一些合理化的机会。如果你可以解决这些问题,那就意味着你了解代码。可能。