根据下一个词在一行中查找一个词
Find a word in a line based on next word
我有一个文件,这里是文件的一部分。所有行中的公共词在这里都是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); }
您可以像这样尝试正则表达式:
public static void main(String[] args) {
String s = "15 EXTR-SITE PIC X.";
System.out.println(s.replaceAll("(.*?\s+)+(.*?)(?=\s+PIC).*", ""));
}
O/P:
EXTR-SITE
解释:
(.*?\s+)+(.*?)(?=\s+PIC).*", "") :
(.*?\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.
--> the contents of the actual String with the first captured group i.e, data between `()`.
PS :这适用于您当前的所有输入:P
//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]);
}
}
请注意,我还没有测试这段代码(但会在几分钟后)。但是,现在一般方法应该很清楚了。
尝试使用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 为您工作,而不是相反。它简洁、可读,然后更可维护.
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 列称为指标区域。它可以是空白的,或者包含一个 *
表示注释,或者一个 -
,表示该行是前一个 non-blank/non-comment 行的延续,或者包含一个 D
表示它是一条调试线。
第 73-80 列可能包含其他序列号、空白或任何内容,必须忽略。
如果您的 COBOL 源代码是 "free format",情况会有所不同,但事实并非如此。
从注释行中提取数据没有任何意义,因此您的预期输出无效。还不清楚您在预期输出中从何处获得破折号。
如果您尝试解析 COBOL 源代码,则必须具有有效的 COBOL 源代码。这是无效的:
TE0305 05 FILLER PIC X(11).
CW0104 10 EXTR-TEXT6 PIC X(67).
CW0104 10 EXTR-TEXT7 PIC X(67).
如果级别编号(05)后面跟着更高级别的编号(两个 10),则它是一个组项目。组项目不能有图片。
PIC本身也可以写全,如PICTURE
PIC 很容易出现在 identifier/data-name (EPIC-CODE) 中。理论上,PICTURE 也可以。
PIC 和 PICTURE 可以出现在注释行中,即使不是注释的代码行。
您要用来查找 "description"(标识符或数据名称)的方法有缺陷。
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).
这只是一个简短的例子,不能被认为是包罗万象的。
由此,您的方法将检索
an-individual-item
COMP-3
and two lines of "whatever happens when PIC is the first thing on line"
为了避免这个问题变成变色龙问题,您需要用不同的方法提出一个新问题(或自己解决)。
根据 COBOL 源的来源,有更好的方法来处理这个问题。如果源代码是 IBM 大型机 COBOL,那么您的源代码应该是编译列表或编译中的 SYSADATA。
从其中任何一个,您都可以在特定条件下的特定位置拿起 identifier/data-name。根本不需要解析。
如果你找不到那个,那我建议你找level-number,然后找到第一个。你还有一些工作要做。
Level-numbers 可以是一位或两位数字,在 1-49 范围内,加上 66、77、88。有些编译器也有 78。如果您的摘录只有 "records"(可能),您就赢了看不到 77 或 78。您可能看不到 66(只看到它使用过一次),很可能会看到 88,您可能希望或可能不希望将其包含在输出中(取决于您需要它的目的)。
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 是相当 "new"(来自 1985 年标准),您很可能没有这些。但你可能会。
上面的输出应该是:
FILLER
FILLER
FILLER
data-name-name-1
data-name-name-2
FILLER
FILLER
FILLER
FILLER
data-name-name-3
data-name-name-4
我不知道你想用那个输出做什么。没有上下文,它没有太多意义。
您选择的方法可能适用于您的实际数据(假设您对样本进行了 pickle,并且您得到的是有效代码)。
不过,说"if the first word on a line is one- or two-digit numeric, if there is a second word, that's what we want, else use FILLER"还是比较简单的。当然,请注意之前关于您应该忽略的内容的评论。
除非您的源包含 88 个级别。因为一系列值需要第二行是很常见的,如果这些值恰好是数字,一个或两个数字,那么这也不起作用。
因此,请确定您的来源。如果它是 IBM 大型机,请尝试从编译中获取输出。那你的任务真的很简单,而且100%准确。
如果你做不到,那就彻底了解你的数据。如果你的结构真的很简单,那么你的方法就可以工作,从级别数开始做仍然会更容易。
如果您需要回到这里,请提出一个新问题。否则你就是在和那些已经花时间自愿回答你现有问题的人闲逛。
如果您不打算自己编写 Cobol 解析器,有几个选项包括:
使用Cobol Compiler处理Cobol copybook。这将以更易于解析的格式创建 Cobol-Copybook 列表。我曾在一些公司工作,这些公司通过在 Hello-World 类型程序中编译 Cobol-Copybook 并处理输出,将所有 Cobol-Copybook 自动转换为等效的 easytrieve copybook。
像 File-Aid 这样的产品有一个 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 copybook的内容:
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,它在树 table 中显示 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); }
您可以像这样尝试正则表达式:
public static void main(String[] args) {
String s = "15 EXTR-SITE PIC X.";
System.out.println(s.replaceAll("(.*?\s+)+(.*?)(?=\s+PIC).*", ""));
}
O/P:
EXTR-SITE
解释:
(.*?\s+)+(.*?)(?=\s+PIC).*", "") :
(.*?\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.
--> the contents of the actual String with the first captured group i.e, data between `()`.
PS :这适用于您当前的所有输入:P
//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]);
}
}
请注意,我还没有测试这段代码(但会在几分钟后)。但是,现在一般方法应该很清楚了。
尝试使用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 为您工作,而不是相反。它简洁、可读,然后更可维护.
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 列称为指标区域。它可以是空白的,或者包含一个 *
表示注释,或者一个 -
,表示该行是前一个 non-blank/non-comment 行的延续,或者包含一个 D
表示它是一条调试线。
第 73-80 列可能包含其他序列号、空白或任何内容,必须忽略。
如果您的 COBOL 源代码是 "free format",情况会有所不同,但事实并非如此。
从注释行中提取数据没有任何意义,因此您的预期输出无效。还不清楚您在预期输出中从何处获得破折号。
如果您尝试解析 COBOL 源代码,则必须具有有效的 COBOL 源代码。这是无效的:
TE0305 05 FILLER PIC X(11).
CW0104 10 EXTR-TEXT6 PIC X(67).
CW0104 10 EXTR-TEXT7 PIC X(67).
如果级别编号(05)后面跟着更高级别的编号(两个 10),则它是一个组项目。组项目不能有图片。
PIC本身也可以写全,如PICTURE
PIC 很容易出现在 identifier/data-name (EPIC-CODE) 中。理论上,PICTURE 也可以。
PIC 和 PICTURE 可以出现在注释行中,即使不是注释的代码行。
您要用来查找 "description"(标识符或数据名称)的方法有缺陷。
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).
这只是一个简短的例子,不能被认为是包罗万象的。
由此,您的方法将检索
an-individual-item
COMP-3
and two lines of "whatever happens when PIC is the first thing on line"
为了避免这个问题变成变色龙问题,您需要用不同的方法提出一个新问题(或自己解决)。
根据 COBOL 源的来源,有更好的方法来处理这个问题。如果源代码是 IBM 大型机 COBOL,那么您的源代码应该是编译列表或编译中的 SYSADATA。
从其中任何一个,您都可以在特定条件下的特定位置拿起 identifier/data-name。根本不需要解析。
如果你找不到那个,那我建议你找level-number,然后找到第一个。你还有一些工作要做。
Level-numbers 可以是一位或两位数字,在 1-49 范围内,加上 66、77、88。有些编译器也有 78。如果您的摘录只有 "records"(可能),您就赢了看不到 77 或 78。您可能看不到 66(只看到它使用过一次),很可能会看到 88,您可能希望或可能不希望将其包含在输出中(取决于您需要它的目的)。
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 是相当 "new"(来自 1985 年标准),您很可能没有这些。但你可能会。
上面的输出应该是:
FILLER
FILLER
FILLER
data-name-name-1
data-name-name-2
FILLER
FILLER
FILLER
FILLER
data-name-name-3
data-name-name-4
我不知道你想用那个输出做什么。没有上下文,它没有太多意义。
您选择的方法可能适用于您的实际数据(假设您对样本进行了 pickle,并且您得到的是有效代码)。
不过,说"if the first word on a line is one- or two-digit numeric, if there is a second word, that's what we want, else use FILLER"还是比较简单的。当然,请注意之前关于您应该忽略的内容的评论。
除非您的源包含 88 个级别。因为一系列值需要第二行是很常见的,如果这些值恰好是数字,一个或两个数字,那么这也不起作用。
因此,请确定您的来源。如果它是 IBM 大型机,请尝试从编译中获取输出。那你的任务真的很简单,而且100%准确。
如果你做不到,那就彻底了解你的数据。如果你的结构真的很简单,那么你的方法就可以工作,从级别数开始做仍然会更容易。
如果您需要回到这里,请提出一个新问题。否则你就是在和那些已经花时间自愿回答你现有问题的人闲逛。
如果您不打算自己编写 Cobol 解析器,有几个选项包括:
使用Cobol Compiler处理Cobol copybook。这将以更易于解析的格式创建 Cobol-Copybook 列表。我曾在一些公司工作,这些公司通过在 Hello-World 类型程序中编译 Cobol-Copybook 并处理输出,将所有 Cobol-Copybook 自动转换为等效的 easytrieve copybook。
像 File-Aid 这样的产品有一个 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 copybook的内容:
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,它在树 table 中显示 COBOL 字帖: