pic x(100) field-a
和
pic x(100) field-b
两者都是左对齐的&资本化。 Field-b-length
是其最后一个非空字节的位置。
我需要进行匹配才能看到field-b
(长度为field-b-length
)是否出现在field-a
的任何位置,即如果field-b = 'DOG'
和field-a = 'MANY PEOPLE LIKE DOGS BUT SOME PREFER CATS (followed by spaces to a length of 100)'
匹配他们。
我查看了INSPECT
语句,但它匹配文字值,而不是变量名称。就像我可以Inspect field-a tallying cnt-1 for all 'DOG'
,而不是INSPECT field-a tallying cnt-1 for all field-b (1 : field-b-length)
,在这种情况下=' DOG'。
Field-a
位于包含2000万条记录的文件中,field-b
位于包含400个条目的文件中,因此作业运行时间超过10小时,我必须运行25个以上的作业,所以我必须针对field-a
文件中的每个条目检查field-b
(读入程序中的数组)。
目前,我确定field-b
的长度并将其与field-a
进行比较,以字节为单位,长度为field-b
。如果任何字节不匹配,我退出,并将field-a
转移到左边,然后再试一次,直到我尝试了(100 - field-b-length)
次。它很难看,但它确实有效。
我一直在寻找更高效,更优雅的东西。
答案 0 :(得分:3)
哪个COBOL不将标识符-3作为标记标准?
这应该有效
01 field-a pic x(100) value
"MANY PEOPLE LIKE DOGS AND CATS AND MORE DOGS".
01 field-b pic x(100) value "DOG".
01 comparison-length pic 999 value 3.
01 found-count pic 999.
01 position-tally pic 999.
...
inspect field-a tallying
found-count for all field-b(1:comparison-length)
if found-count greater than zero then
display "Found " found-count " occurrences" end-display
else
display
"No " field-b(1:comparison-length) " found"
end-display
end-if
move "HORSE" to field-b
move zero to comparison-length
inspect field-b tallying comparison-length
for characters before initial space
inspect field-a tallying position-tally
for characters before initial field-b(1:comparison-length)
if position-tally less than length of field-a then
display "Found at " position-tally end-display
else
display
"No " field-b(1:comparison-length) " found"
end-display
end-if
给
Found 002 occurrences
No HORSE found
但是,这是用GnuCOBOL测试的,所以我对你的特定编译器感到好奇。
编辑;由于比尔伍德的评论,代码略有变化。留下两种检测子串的样式,只是因为
答案 1 :(得分:2)
首先,您的数据名称不会编译,至少是标准。忽略您忽略了级别编号,字段的名称(如果存在)必须遵循级别编号。然后,数据定义的子句可以按您喜欢的任何顺序排列。
其次,“丑陋但工作”不起作用,你只是没有测试极限。将DOG置于位置98,99和100,然后尝试(100-3)尝试从位置1找到DOG。第一次尝试将从位置1开始,第97次尝试将从位置97开始。第98个字节将永远不会用作起点,因此尾随的DOG永远不会匹配。关接一个。关闭的情况的青蛙。关逐狗。
正如Brian Tanner所说,INSPECT
确实做了你想做的事。 INSPECT的优势在于,对于三字节参考修改,您的数据可以从位置98开始并仍然匹配。 INSPECT已经为您编码。
由于您没有说您需要所有DOG的计数,只是知道它在那里,然后使用FIRST
,而不是ALL
。找到匹配项后,INSPECT将“停止”。这只会影响“匹配”的表现,但仍然不需要额外做其他事情。
INSPECT是否是最快的方法,取决于您使用的实际编译器中的实现。因此,如果急需速度(每天需要的任务,每天五次)测试它,并看看它如何影响您的性能要求。
如果您需要寻找更快的速度,您需要更好地了解数据。
在IBM的企业COBOL中,使用TALLYING,ALL进行INSPECT(不能像我最初建议的那样使用FIRST,只能在INSPECT上使用REPLACING)和参考修改字段是最快的通用方式,并且只有如果你要求表现出比你更好的表现,你应该去别处看看。
有许多“搜索”任务可以考虑INSPECT,通常是:它是否存在(你的任务);那里有多少;在哪里?
对于前两个,用TALLYING和ALL进行检查。虽然如果唯一的需要是知道存在或其他方面,计算所有这些似乎是迟钝的,这个版本的INSPECT是最快的方法。如果它计数一个,然后继续到最后仍在搜索,它只会在匹配的记录上执行此操作。 INSPECT的替代使用,在......之前计算所有字符,是“非常慢”(相对术语)。
要以最有效的方式罚款起始位置,首先要检查是否有需要寻找的东西。然后,使用循环查找数据(您将知道它在那里,因此您不需要检查该字段的“溢出”)。
这些对INSPECT性能的引用可能不适用于您的特定编译器,因为它完全取决于实现。
与往常一样,由于性能问题,数据的实际性质将帮助您选择最佳方式。上面的建议持有(给定编译器)“正常”数据。如果您的数据不是特别“正常”,那么专注于不正常的数据将有所帮助。
假设2000万条记录中有90%的数据要搜索的数据为30字节或更少。
01 field-to-search.
05 mostly-data-here PIC X(30).
05 sometimes-data-here PIC X(70).
88 only-the-short-data VALUE SPACE.
IF only-the-short-data
INSPECT mostly-data-here ...
ELSE
INSPECT field-to-search ...
END-IF
因此,90%的INSPECT只会占用30个字节,代价是使用88测试空间的IF。这只是你可以做的一个变化 - 最好的取决于数据。理解数据。考虑几种可行的方法。测试以确认它们是否有效。使用反映现实的数据进行体积测试。还有完全不同数据的体积测试。根据数据的不同,不同的解决方案可以更快或更慢。
答案 2 :(得分:-1)
听起来好像你应该使用数据库。将两个文件加载到表中然后使用SELECT ... WHERE
子句执行LIKE
是值得的。我希望整个过程能在几分钟内完成。