0

我有以下来自 apache 的行(更改 apache 日志格式不是一种选择):

... referrer=- user_agent=JSON-RPC Client status=200 size=44 ...

我正在尝试用 Ragel 解析它。我正在提取除 user_agent 之外的所有字段。用户指南说,强烈的差异--确保第一台机器不包含第二台机器。就我而言,我想匹配任何不包含的内容" status=",这将表示下一个字段。但是,我目前的定义(如下)似乎user_agent完全跳过了;我仍然得到status并关注领域。我是否正确利用了强烈的差异?

...
referrer   = ^space+             >mark %{ emit("referrer"); };
user_agent = any* -- ' status=' >mark %{ emit("user_agent"); };
status     = digit+              >mark %{ emit("status"); };
...

line = ( 
  ... 
  space "referrer=" 
  referrer 
  space "user_agent="
  user_agent
  space "status="
  status
  space "size="
  ...
);
4

2 回答 2

1

我知道这个问题很老,但我刚刚进入 Ragel,这可能对其他人有所帮助。

这里的问题是运算符优先级。动作运算符>%在强差分运算符之前进行评估--。用括号很容易修复:

user_agent = (any* -- ' status=') >mark %{ emit("user_agent"); };

我也会使用space而不是硬编码一个空间,至少为了一致性:

user_agent = (any* -- (space 'status=')) >mark %{ emit("user_agent"); };
于 2015-12-22T13:17:00.560 回答
0

你可以使用状态图,试试这个状态机:

STATUS := digit+ ' ' @{ fnext SIZE; };
SIZE   := digit+;

USER_AGENT =
    start: (
        's'    -> s1 |
        [^s] @{ if (!ua_start) ua_start = p; }  -> start
    ),
    s1: (
        't'  -> s2 |
        [^t] -> start
    ),
    s2: (
        'a'  -> s3 |
        [^a] -> start
    ),
    s3: (
        't'  -> s4 |
        [^t] -> start
    ),
    s4: (
        'u'  -> s5 |
        [^u] -> start
    ),
    s5: (
        's'  -> s6 |
        [^s] -> start
    ),
    s6: (
        '='  @{ fnext STATUS; ua_stop = p - 7; } -> final |
        [^=] -> start
    )
    ;

main := "user_agent=" USER_AGENT ;

您可以在“ua_start”->“ua_stop”中获取用户代理,对于其他变量,我想您已经知道如何标记和获取字符。

于 2013-06-06T11:01:36.947 回答