我有一个文件,这是文件的一部分。所有行中的常用词是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); }
答案 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 副本:
答案 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为你工作,而不是相反。它简洁,可读,然后更可维护。