【发布时间】:2015-12-24 13:46:35
【问题描述】:
我们正在尝试为路由器中生成的日志文件构建解析器。 我们成功构建并能够在特定文件中打印有效语言。
但是如果根据语法输入是无效的,那么我们想在不同的文件中打印它。我们尝试了一些东西,但它不能正常工作。 你能建议我们做这件事的方法吗?如果可能,请给出工作示例。
这是我们尝试过的。
我们没有使用任何特定的 IDE,只是一个文本编辑器。 vANTLR-4.5
我们的输入:(input.txt)
Dec 24 15:38:13 103.199.144.14 firewall,info NAT: src-nat2 srcnat: in:(none) out:ether1-WAN, proto TCP (SYN), 10.20.114.212:59559->86.96.88.147:6882, len 52
Dec 24 15:38:13 103.199.144.14 firewall,info src-nat2: forward: in:<pppoe-PDR242> out:ether1-WAN, proto TCP (SYN), 10.20.124.8:50055->111.111.111.111:80, len 52
第一行是无效语言。并且不应该通过语法,因此必须打印到failure.txt中,但是部分打印在success.txt文件中。
而第二行是有效的,并且在 success.txt 文件中正确打印,如下面的输出文件所示。
我们得到的输出:(success.txt)
Dec 24 15:38:13, 103.199.144.14, .20.114.212, len, 52, , null
Dec 24 15:38:13, 103.199.144.14, pppoe-PDR242, TCP, 10.20.124.8:50055, 111.111.111.111:80, null
语法,我们使用的是:(sys.g)
grammar sys;
r: IDENT NUM time ip x+ user xout proto xuser ipfull xtra ipfull1 xtra1 (xipfull xtra ipfull2 xtra2 xipfull xtra3)*;
time: NUM COLN NUM COLN NUM;
ip: NUM DOT NUM DOT NUM DOT NUM ;
ipfull: NUM DOT NUM DOT NUM DOT NUM COLN NUM ;
ipfull1: NUM DOT NUM DOT NUM DOT NUM COLN NUM ;
ipfull2: NUM DOT NUM DOT NUM DOT NUM COLN NUM ;
xipfull: NUM DOT NUM DOT NUM DOT NUM COLN NUM ;
x: (IDENT | COMMA | COLN | BRAC | HYPHN | NUM)+ LTHAN;
user: (IDENT | HYPHN | DOT | NUM)+ ;
xout: GTHAN IDENT+ COLN IDENT+ HYPHN IDENT+ (DOT IDENT)* COMMA IDENT;
proto: IDENT ;
xuser: (IDENT | BRAC | COMMA)+ ;
xtra: HYPHN GTHAN ;
xtra1: COMMA IDENT (BRAC | NUM);
xtra2: BRAC xtra;
xtra3: COMMA IDENT NUM;
IDENT: ('a'..'z' | 'A'..'Z')('a'..'z' | 'A'..'Z' | '0'..'9')* ;
NUM: ('0'..'9')+ ;
LTHAN: '<' ;
GTHAN: '>' ;
COLN: ':';
COMMA: ',';
BRAC: '(' | ')' ;
HYPHN: '-';
DOT: '.';
WS : (' ' | '\t' | '\r' | '\n')+ -> skip ;
我们使用语法生成的 Parser 和 lexer 的主类。
import org.antlr.v4.runtime.ANTLRFileStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import java.io.*;
import org.antlr.v4.runtime.*;
public class SysLogCheck {
public static void main(String[] args) throws Exception {
long startTime = System.currentTimeMillis();
BufferedReader br = new BufferedReader(new FileReader("test123.txt"));
String s = null;
//FileWriter out = new FileWriter("abc.txt");
PrintWriter success = new PrintWriter(new FileWriter("success.csv"));
PrintWriter failure = new PrintWriter(new FileWriter("failure.csv"));
while((s=br.readLine())!=null)
{
ANTLRInputStream input = new ANTLRInputStream(s);
sysLexer lexer = new sysLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
sysParser parser = new sysParser(tokens);
ParseTree tree = parser.r();
EvalVisitor visitor = new EvalVisitor();
if((visitor.visit(tree)).equals("failure")) // here visit method of EvalVisitor class returns "failure" then the content should be written
//in failure file and else it should be written in success file
// but this is not working
{
failure.println(s);
}
else
{
success.println(visitor.visit(tree));
}
}
failure.flush();
failure.close();
success.flush();
success.close();
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
System.out.println(elapsedTime);
}
}
我们的 EvalVisitor(主要访问者类)代码:
import org.antlr.v4.runtime.tree.ParseTree;
import java.io.*;
public class EvalVisitor extends sysBaseVisitor
{
class LogEntry {
String ident1;
String dayNum;
String time;
String ip;
String ipfull;
String user;
String proto;
String ipfull1;
String ipfull2;
String x;
}
static LogEntry logEntry;
@Override
public Object visit(ParseTree tree) {
/* Setup logentry used by all visitors (this case, there is only a single visitor...)*/
logEntry = new LogEntry();
final Object o = super.visit(tree);
//our logic to check whether our input contains "<" or not
if((logEntry.x).contains("<") )
{
return logEntry.ident1 +" " + logEntry.dayNum + " " + logEntry.time+ ", " + logEntry.ip+ ", " + logEntry.user+ ", " + logEntry.proto+ ", " + logEntry.ipfull+ ", " + logEntry.ipfull1+ ", " + logEntry.ipfull2;
}
return "failure"; //else return failure
}
StringBuilder stringBuilder;
@Override
public Object visitR(sysParser.RContext ctx) {
logEntry.ident1 = ctx.IDENT().getText();
logEntry.dayNum = ctx.NUM().getText();
return super.visitR(ctx);
}
@Override
public Object visitTime(sysParser.TimeContext ctx) {
logEntry.time = ctx.getText();
return super.visitTime(ctx);
}
@Override
public Object visitIp(sysParser.IpContext ctx) {
logEntry.ip = ctx.getText();
return super.visitIp(ctx);
}
@Override
public Object visitIpfull(sysParser.IpfullContext ctx) {
logEntry.ipfull = ctx.getText();
return super.visitIpfull(ctx);
}
@Override
public Object visitIpfull1(sysParser.Ipfull1Context ctx) {
logEntry.ipfull1 = ctx.getText();
return super.visitIpfull1(ctx);
}
@Override
public Object visitIpfull2(sysParser.Ipfull2Context ctx) {
logEntry.ipfull2 = ctx.getText();
return super.visitIpfull2(ctx);
}
@Override
public Object visitXipfull(sysParser.XipfullContext ctx) {
return super.visitXipfull(ctx);
}
@Override
public Object visitX(sysParser.XContext ctx) {
logEntry.x = ctx.getText();
return super.visitX(ctx);
}
@Override
public Object visitUser(sysParser.UserContext ctx) {
logEntry.user = ctx.getText();
return super.visitUser(ctx);
}
@Override
public Object visitXuser(sysParser.XuserContext ctx) {
return super.visitXuser(ctx);
}
@Override
public Object visitXout(sysParser.XoutContext ctx) {
return super.visitXout(ctx);
}
@Override
public Object visitProto(sysParser.ProtoContext ctx) {
logEntry.proto = ctx.getText();
return super.visitProto(ctx);
}
@Override
public Object visitXtra(sysParser.XtraContext ctx) {
return super.visitXtra(ctx);
}
@Override
public Object visitXtra1(sysParser.Xtra1Context ctx) {
return super.visitXtra1(ctx);
}
@Override
public Object visitXtra2(sysParser.Xtra2Context ctx) {
return super.visitXtra2(ctx);
}
@Override
public Object visitXtra3(sysParser.Xtra3Context ctx) {
return super.visitXtra3(ctx);
}
}
【问题讨论】:
-
是的。两个人的团队。