根据下一个单词在一行中查找单词

时间:2015-03-06 05:59:12

标签: java cobol

我有一个文件,这是文件的一部分。所有行中的常用词是PIC,我能够找到PIC的索引。我试图提取每行的描述。在这里,如何在单词PIC之前提取单词?

          15 EXTR-SITE                                 PIC X.
        05 EXTR-DBA                                    PIC X.
TE0305*     05 EXTR-BRANCH                         PIC X(05).
TE0305*     05 EXTR-NUMBER                         PIC X(06).
TE0305      05 FILLER                                  PIC X(11).
CW0104        10 EXTR-TEXT6                       PIC X(67).
CW0104        10 EXTR-TEXT7                       PIC X(67).
CW0104*     05 FILLER                                  PIC X(567).

我必须得到如下的结果

EXTR-SITE 
EXTR-DBA
EXTR-NUMBER
-------
FILLER

我可以使用任何表达式来找到'PIC'之前的单词吗?

以下是获取包含'PIC'的行的代码:

int wordStartIndex = line.indexOf("PIC");
int wordEndIndex = line.indexOf(".");
if ((wordStartIndex > -1) && (wordEndIndex >= wordStartIndex)) {
System.out.println(line); }

5 个答案:

答案 0 :(得分:3)

          15 EXTR-SITE                                 PIC X.
        05 EXTR-DBA                                    PIC X.
TE0305*     05 EXTR-BRANCH                         PIC X(05).
TE0305*     05 EXTR-NUMBER                         PIC X(06).
TE0305      05 FILLER                                  PIC X(11).
CW0104        10 EXTR-TEXT6                       PIC X(67).
CW0104        10 EXTR-TEXT7                       PIC X(67).
CW0104*     05 FILLER                                  PIC X(567).

我认为在您完成此任务之前,您需要了解有关COBOL的更多信息。

第1-6列可以包含序列号,可以为空白,也可以包含任何内容。如果您尝试解析COBOL代码,则需要忽略第1-6列。

第7列称为指标区域。它可以是空白,或者包含表示注释的*,或者-,表示该行是前一个非空白/非注释行的延续,或者包含{{ 1}}表示它是一个调试行。

第73-80列可能包含另一个序列号,或空白或任何内容,必须忽略。

如果您的COBOL源是“自由格式”,那么事情会有所不同,但事实并非如此。

从注释行提取数据没有任何意义,因此您的预期输出无效。目前还不清楚你在预期输出中得到破折号的位置。

如果您尝试解析COBOL源,则必须具有有效的COBOL源。这是无效的:

D

如果级别编号(05)后跟更高级别的数字(两个10),则该级别编号(05)是一个组项目。小组项不能拥有PICture。

PIC本身也可以完整写入,如PICTURE。

PIC很容易出现在标识符/数据名称(EPIC-CODE)中。从理论上讲,这可能是图片。

即使不是注释的代码行,PIC和PICTURE也可能出现在注释行中。

您要用来查找“描述”(标识符或数据名称)的方法存在缺陷。

TE0305      05 FILLER                                  PIC X(11).
CW0104        10 EXTR-TEXT6                       PIC X(67).
CW0104        10 EXTR-TEXT7                       PIC X(67).

这只是一个简短的例子,不应被视为无所不包。

由此,您的方法将检索

   01  the-record.
       05  fixed-part-of-record.
           10  an-individual-item PIC X.
           10  another-item COMP-1.
           10  and-another COMP-3 PIC 9(3).
           10  PIC X.
       05  variable-part-of-record.
           10  entry-name OCCURS 10 TIMES.
               15  entry-name-client-first-name
                                  PIC X(30).
               15  entry-name-client-surname
                                  PIC X(30).

为了保存这个成为变色龙的问题,你需要用不同的方法提出一个新问题(或者自己解决)。

根据COBOL源的来源,有更好的方法来解决这个问题。如果源是IBM Mainframe COBOL,那么源的源应该是编译列表或编译中的SYSADATA。

在其中任何一个中,您将在特定条件下的特定位置选取标识符/数据名称。根本没有解析。

如果你不能那样做,那么我建议你找一下等级号码,然后找到第一件事。你还有一些工作要做。

级别数字可以是一个或两个数字,范围是1-49,加上66,77,88。有些编译器也有78个。如果你的提取只是“记录”(可能),你将看不到77或78.你可能看不到66(只看过它曾经使用过一次)并且很可能会看到88s,你可能想要或不想把它们包括在你的输出中(取决于你需要它)。

an-individual-item
COMP-3
and two lines of "whatever happens when PIC is the first thing on line"

使用单位数字表示级别号而不是拼写FILLER显然是相当“新的”(来自1985年标准),你很可能没有任何这些。但你可能会。

以上输出应为:

1.
01.
01  FILLER.
01  data-name-name-1.
01  data-name-name-2 PIC X(80).
    5.
    05.
    05  FILLER.
    05  FILLER PIC X.
    05  data-name-name-3.
    05  data-name-name-4 PIC X.

我不知道您想要对该输出做什么。没有上下文,它没有太多意义。

您选择的方法可能适用于您的实际数据(假设您腌制了样本,并且您获得的是有效代码)。

然而,如果“一行中的第一个单词是一位或两位数字,如果有第二个单词,那就是我们想要的,或者使用FILLER”,那么仍然会更简单。当然,请注意以前关于你应该忽略的内容的评论。

除非您的来源包含88个级别。因为一系列值需要第二行是很常见的,并且如果值恰好是数字,一个或两个数字,那么这也不会有效。

因此,请确定您的来源。如果是IBM Mainframe,请尝试从编译中获取输出。然后你的任务非常简单,并且100%准确。

如果无法做到,请彻底了解您的数据。如果您的方法非常简单,那么您的方法可以正常工作,那么从级别编号开始执行它仍然会更容易。

如果您需要回复此问题,请提出新问题。否则你就是在为那些已经花时间自愿回答你现有问题的人们晾晒。

答案 1 :(得分:3)

如果您不致力于自己编写Cobol解析器,可以选择以下几种方法:

  • 使用 Cobol编译器处理Cobol副本。这将以更易于解析的格式创建Cobol-Copybook列表。我曾经通过在Hello-World类型程序中编译Cobol-Copybook并处理输出,自动将所有 Cobol -Copybooks转换为等效的easytrieve copybooks。

  • 文件辅助这样的产品有一个Cobol解析器,可以生成一个易于消化的Cobol Copybook版本。

  • java项目cb2xml会将Cobol-Copybook转换为 Xml 。该项目提供了一些使用Jaxb处理Xml的示例。


使用 cb2xml (取自Demo2.java)将Cobol-Copybook解析为Java项目列表:

JAXBContext jc = JAXBContext.newInstance(Condition.class, Copybook.class, Item.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
Document doc = Cb2Xml2.convertToXMLDOM(
                       new File(Code.getFullName("BitOfEverything.cbl").getFile()),
                       false,
                       Cb2xmlConstants.USE_STANDARD_COLUMNS);
JAXBElement<Copybook> copybook = unmarshaller.unmarshal(doc, Copybook.class);

程序Demo2.java将打印出cobol副本的内容:

List<Item> items = copybook.getValue().getItem();
for (Item item : items) {
    Code.printItem(" ", item);
}

打印Cobol-Item Code.java

public static void printItem(String indent, Item item) {
    char[] nc = new char[Math.max(1, 50 - indent.length()
                                        - item.getName().length())];
    String picture = item.getPicture();
    Arrays.fill(nc, ' ');
    if (picture == null) {
        picture = "";
    }
    System.out.println(indent + item.getLevel() + " " + item.getName() 
              + new String(nc) + item.getPosition()
              + " " + item.getStorageLength() + "\t" + picture);
    List<Item> childItems = item.getItem();
    for (Item child : childItems) {
        printItem(indent + " ", child);
    }
} 

Demo2 的输出就像(给你关卡,字段名称,开头,长度和图片):

   01 CompFields                                     1 5099 
      03 NumA                                        1 25   --,---,---,---,---,--9.99
      03 NumB                                        26 3   9V99
      03 NumC                                        29 3   999
      03 text                                        32 20  x(20)
      03 NumD                                        52 3   VPPP999
      03 NumE                                        55 3   999PPP
      03 float                                       58 4   
      03 double                                      62 8   
      03 filler                                      70 23  
         05 RBI-REPETITIVE-AREA                      70 13  
            10 RBI-REPEAT                            70 13  
               15 RBI-NUMBER-S96SLS                  70 7   S9(06)
               15 RBI-NUMBER-S96DISP                 77 6   S9(06)
         05 SFIELD-SEP                               83 10  S9(7)V99

另一个 cb2xml 示例是DemoCobolJTreeTable.java,它在树表中显示 COBOL 副本:

Cobol-Copybook displayed in a Tree Table

答案 2 :(得分:1)

您可以尝试这样的正则表达式:

public static void main(String[] args) {
    String s = "15 EXTR-SITE                                 PIC X.";
    System.out.println(s.replaceAll("(.*?\\s+)+(.*?)(?=\\s+PIC).*", "$1"));
}

O / P:

EXTR-SITE

说明:

(.*?\\s+)+(.*?)(?=\\s+PIC).*", "$1") :

(.*?\\s+)+ --> Find one or more groups of "anything" which is followed by a space.

(.*?)(?=\\s+PIC) -->find a group of "any set of characters" which are followed by a space and the word "PIC".
.* --> Select everything after PIC.

$1 --> the contents of the actual String with the first captured group i.e, data between `()`.

PS:这适用于您当前的所有输入:P

答案 3 :(得分:0)

//let 'lines' be an array of all your lines 
//with one complete line as string per element

for(String line : lines){ 
   String[] splitted = line.split(" ");
   for(int i = 0; i < splitted.length; i++){
       if(splitted[i].equals("PIC") && i > 0) System.out.println(splitted[i-1]);
   }
}

请注意,我还没有测试此代码(但会在几分钟内完成)。然而,现在的一般方法很明显。

答案 4 :(得分:0)

尝试使用String.split("\\s+")。此方法将原始字符串拆分为字符串数组(String[])。然后,使用Arrays.asList(...)您可以将数组转换为List,这样您就可以使用indexOf搜索特定对象。

以下是可能解决方案的摘录:

String words = "TE0305*     05 EXTR-BRANCH                         PIC X(05).";
List<String> list = Arrays.asList(words.split("\\s+"));
int index = list.indexOf("PIC");
// Prints EXTR-BRANCH
System.out.println(index > 0 ? list.get(index - 1) : ""); // Added a guard

在我看来,这段代码让Java为你工作,而不是相反。它简洁,可读,然后更可维护