我对正则表达式比较陌生,我不确定这是解决问题的方法,但现在可以了。
我的文本文件可能包含以下内容:
program A {
int x = 10;
tuple date {
int day;
int month;
int year;
}
}
function B {
int y = 20;
...
}
process C {
more code;
}
我需要提取程序或函数或进程之间的任何文本。所以只有3种类型的标题。
所以我决定使用正则表达式来获取大括号之间的任何文本。我开始的方式是通过这个表达式,假设我事先知道标识符列表:
(program|function|process)+ A[\s\S]*(?=function)
这样可以很好地捕获程序A中的任何文本。但有时程序A可能不会被函数跟随。随后可以是流程或其他程序。在我的最后一组中添加OR后,它将无法正常工作。
(program|function|process)+ A[\s\S]*(?=function|process|program)
我看到它的方式是通过3个选项:
提前致谢!
PS:我用它来帮助RegExpr:http://gskinner.com/RegExr/?33i30
答案 0 :(得分:4)
您应该考虑使用LL解析器而不是regexp。正则表达式不是解决每个解析需求的正确答案,而是仅适用于常规语言。如果您有无上下文语法,请使用LL解析器。
答案 1 :(得分:1)
如果您更喜欢正则表达式解决方案,请尝试以下方法:
/(program|function|process).*?{(.*?)}\n+(program|function|process)/m
您可能需要对其进行测试here。
然而,正则表达式解决方案对您的问题并不健全。在使用之前我们必须做出一些假设。例如,代码需要格式良好。玩它以防万一它应该为你提供一个解决方法。
更新:这是经过测试的Java代码:
public class Test {
public static void main(String[] args) throws IOException {
String input = FileUtils.readFileToString(new File("input.txt"));
Pattern p = Pattern.compile("(?<=program|function|process)[^{]*\\{(.*?)\\}\\s*(?=program|function|process|$)", Pattern.DOTALL);
Matcher m = p.matcher(input);
while(m.find()) {
System.out.println(m.group(1));
}
}
}
答案 2 :(得分:1)
如果你真的不想使用语法,你可以实现一个简单的解析器,它可以逐行分析文件:
请看我的例子:
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils;
public class SourceCodeProgram {
public static void main(String[] args) throws Exception {
File source = new File("C:\\test.txt");
SourceCodeScanner scanner = new SourceCodeScanner(source);
for (Code code : scanner.readAll()) {
System.out.println(code);
System.out.println("-----------");
}
}
}
class SourceCodeScanner {
private File source;
private Pattern startCodePattern = Pattern.compile(
"^(\\s)*(program|function|process)", Pattern.CASE_INSENSITIVE);
public SourceCodeScanner(File source) {
this.source = source;
}
public Collection<Code> readAll() throws Exception {
List<String> lines = readFileLineByLine();
List<Code> codes = new ArrayList<Code>();
StringBuilder builder = new StringBuilder(512);
for (String line : lines) {
if (containsSourceCodeHeader(line)) {
int length = builder.length();
if (length != 0) {
codes.add(new Code(builder.toString().trim()));
builder.delete(0, length);
}
}
addNextLineOfSourceCode(builder, line);
}
String lastCode = builder.toString();
if (containsSourceCodeHeader(lastCode)) {
codes.add(new Code(builder.toString().trim()));
}
return codes;
}
private boolean containsSourceCodeHeader(String line) {
return startCodePattern.matcher(line).find();
}
private void addNextLineOfSourceCode(StringBuilder builder, String line) {
builder.append(line);
builder.append(IOUtils.LINE_SEPARATOR);
}
private List<String> readFileLineByLine() throws Exception {
FileInputStream fileInputStream = new FileInputStream(source);
return IOUtils.readLines(new BufferedInputStream(fileInputStream));
}
}
class Code {
private String value;
public Code(String value) {
this.value = value;
}
public String getValue() {
return value;
}
@Override
public String toString() {
return value;
}
}