解析错误原始字符串并有效地选择错误类型

时间:2014-09-20 23:28:46

标签: php parsing optimization

所以我遇到以下情况:一个进程正在将大量数据传输到我用来解析然后将一些信息存储在数据库中的PHP脚本中。

输入数据是一个多行字符串,但对我来说真正重要的是找到特定的关键字,然后说输入数据是1到n类型的错误。

我有一个这样的数组:

$errors = [ 
1 => [
        "error 4011",
        "clp-no",

     ],
2 => [
        "error 4012",
        "clp-nf",
        "0010x100"
     ],
];

想法是说出错误是什么键 - 数组键是错误号。目前我有这段代码来处理这种情况:

$errorId = 25; // Default error for undetected / others
foreach ($errors as $ierrorId => $matches) {
    foreach ($matches as $match) {
        if (mb_stripos($raw, $match) !== false) {
            $errorId = $ierrorId;
            break 2;
        }
    }
}

这段代码工作正常,但是,当我查看进程向其转储信息时的资源使用情况时,看起来有一个瓶颈...(通常运行20次左右会处理大约10或20个字符串。)

建议的方法是使用最少的资源使用来完成我想要完成的任务?


代码的输出是错误的ID。错误的ID是$errors数组的数字键之一。

此代码基本上将可能存在相同错误的消息分组,然后为我提供唯一的错误ID。

谢谢。

此解析的$raw输入示例:

[0]: error 4011 processing request

No input data: clp-nf 

This is an automated message from the PTD daemon 
    => Error: 0010x111.

还有其他一些,底线是:格式可以改变,我不能依赖位置和东西,它必须尝试找到数组上的一个字符串,然后返回数组键。例如,第二条消息将输出2,因为clp-nf可以在数组的第二个位置找到。

1 个答案:

答案 0 :(得分:1)

我使用不同的函数进行了一些基准测试,以查找文本字符串。

  • mb_stripos(不区分大小写)
  • mb_strpos(区分大小写)
  • mb_strposstrtolower关于要搜索的字符串和错误字符串

我还尝试了上面发布的嵌套数组结构,以及一个平面错误列表,其中键是错误字符串,值是错误编号。以下是我在一组示例字符串上运行20,000次重复的结果(所有返回相同的错误集),其中包含一个包含六个不同错误字符串的数组,包括一个包含非ASCII字符的错误字符串:

[nested_stripos] => 178.60633707047s
[nested_strpos] => 19.614015340805s
[nested_strpos_with_strtolower] => 25.815476417542s
[flat_stripos] => 177.30470108986s
[flat_strpos] => 18.139512062073s
[flat_strpos_with_strtolower] => 24.32790517807s

正如您所看到的,与mb_stripos相比,使用mb_strpos的速度非常慢。如果您不知道错误将在哪种情况下,将所有内容转换为小写比使用mb_stripos要快得多。使用平面列表比嵌套数组略快于20,000次重复,但除非您的原始输入很大,否则不太可能有明显的差异。

我没有测试preg_match因为众所周知正则表达式比字符串匹配慢。

如果您开始记录匹配的错误字符串(例如error 40120010x001),您可以构建频率表并按错误字符串排序最常出现的错误字符串。

这是最快的功能:

# lines: an array of text strings, including several with non-ASCII characters
# $err_types: data structure holding the error messages to search for (see below)
function flat_strpos($err_types, $lines){
    $list = array();
    foreach ($lines as $l) {
        $err = 25;
        foreach ($err_types['flat'] as $e => $no) {
            if (mb_strpos($l, $e) !== false) {
                $err = $no;
                break;
            }
        }
        $list[] = "ERR $err; content: " . mb_substr($l, 0, 100);
    }
    return $list;
}

供参考,$err_type数据结构:

$err_types = [
    'flat' => [
        'error 4011' => 1,
        'clp-no' => 1,
        'error 4012' => 2,
        'clp-nf' => 2,
        '0010x100' => 2,
        '颜色' => 3
    ],
    'nested' => [
        1 => [
            'error 4011',
            'clp-no'
        ],
        2 => [
            'error 4012',
            'clp-nf',
            '0010x100'
        ],
        3 => [
            '颜色'
        ]
    ]
];