Php 将字符串变形为模式

Php 将字符串变形为模式,php,regex,Php,Regex,我正在研究一个问题,在这种情况下,用户卡车司机使用短信发送有关工作状态的信息。我想保持键控简单,因为并非所有用户都有智能手机,所以我采用了一些简单的短代码作为他们的输入。以下是一些示例及其含义: P123456-3用于装载123456-3 D456789-1,用于荷载下降456789-1 L345678-9加载345678-9将延迟 这很简单,但用户和卡车司机会以一些不正常的方式键入更新,例如: D 456789-1 D 456789-1 D.456789-1我看这批货是湿的,我们需要取消订单吗

我正在研究一个问题,在这种情况下,用户卡车司机使用短信发送有关工作状态的信息。我想保持键控简单,因为并非所有用户都有智能手机,所以我采用了一些简单的短代码作为他们的输入。以下是一些示例及其含义:

P123456-3用于装载123456-3 D456789-1,用于荷载下降456789-1 L345678-9加载345678-9将延迟 这很简单,但用户和卡车司机会以一些不正常的方式键入更新,例如:

D 456789-1 D 456789-1 D.456789-1我看这批货是湿的,我们需要取消订单吗 你几乎可以想出一打其他的排列,我不难捕捉并修复那些我能想象到的排列

我通常使用正则表达式来测试输入是否符合我想象中的坏模式,然后提取出我认为是好的部分,将它们重新组装成正确的顺序

正是这些新错误导致了我的问题,所以我想知道是否有一种更通用的方法,可以将模式和消息传递给函数,最好将消息转换为与模式匹配的内容


我的搜索没有找到任何真正适合我尝试做的事情,我甚至不确定是否有一个好的通用方法来做到这一点。我碰巧在这个实现中使用了PHP,但任何类型的示例都会有所帮助。你们有谁有办法吗?

如果用户对您的软件有问题,请修复软件,而不是用户

问题的出现是因为您的格式看起来很复杂。你为什么一开始就需要哈希?将其简化为以下内容如何:

 operation-code maybe-space load-number maybe-space and comment
操作码分配给不同的手机按键,因此J、K和L的含义相同。荷载编号可以数字和字母形式发送,例如agja表示2452。用户使用这种格式很难出错

下面是一些代码来说明这种方法:

function parse($msg) {

    $codes = array(
        3 => 'DROP',
        5 => 'LOAD',
        // etc
    );

    preg_match('~(\S)\s*(\S+)(\s+.+)?~', $msg, $m);
    if(!$m)
        return null; // cannot parse

    $a = '.,"?!abcdefghijklmnopqrstuvwxyz';
    $d = '1111122233344455566677777888999';

    return array(
        'opcode'  => $codes[strtr($m[1], $a, $d)],
        'load'    => intval(strtr($m[2], $a, $d)),
        'comment' => isset($m[3]) ? trim($m[3]) : ''
    );
}

print_r(parse(' j ww03 This load looks wet to me'));
//[opcode] => LOAD
//[load] => 9903
//[comment] => This load looks wet to me

print_r(parse('dxx0123'));
//[opcode] => DROP
//[load] => 990123
//[comment] => 
差不多

/^[#\s]*([PDL])[#\s]*(\d+[\s-]+\d)/
或者更放松一点,

/^[^\d]*([PDL])[^\d]*(\d+)[^\d]+(\d)/

你会得到你想要的。但我更喜欢哈姆扎的评论作为解决方案:把它扔回去,告诉他们一起行动:

首先,去掉不应该出现的东西:

$str = preg_replace('/[^PDL\d-]/i', '', $str);
这将为您提供以下标准化结果:

D456789-1 D456789-1 D456789-1LDLDLD 然后,尝试匹配所需的数据:

if (preg_match('/^([PDL])(\d+-\d)/i', $str, $match)) {
    $code = $match[1];
    $load = $match[2];
} else {
    // uh oh, something wrong with the format!
}

试着这样做:

function parse($input) {
    // Clean up your input: 'D#.456789 - 1 foo bar' to 'D 456789 1 foo far'
    $clean = trim(preg_replace('/\W+/', ' ', $input));
    // Take first 3 words.
    list($status, $loadId1, $loadId2) = explode(' ', $clean);
    // Glue back your load ID to '456789-1'
    $loadId = $loadId1 . '-' . $loadId2;
    return compact('status', 'loadId');
}
例如:

$inputs = array(
    'P#123456-3',
    '#D 456789-1',
    'D# 456789 - 1',
    'D#.456789-1 This load looks wet to me do weneed to cancelthis order',
);
echo '<pre>';
foreach ($inputs as $s) {
    print_r(parse($s));
}

你为什么不发一条短信告诉司机发送的代码不符合规定的格式?我不确定是否有一种“一网打尽”的方法。看看答案中的建议会很有趣。不幸的是,我能想象的最安全的方式是使用移动应用程序,而不是依赖原始用户输入。允许用户选择一个状态,然后选择一个作业编号,它仍然可以发出一条文本。或者将正则表达式和前面的注释组合起来,尝试捕捉错误类型,如果全部失败,则返回响应。错误>请仅输入代码。没有空格,没有点,没有注释。THXAll好主意,但遗憾的是,我们正在处理来自其他公司甚至跨境的用户驱动程序。发送一个纠正短信回来正在做,但我想消除尽可能多的。驱动程序通常无法在几个小时内检查消息以解决问题。我正在认真考虑一款手机应用程序,但仍有相当多的司机没有智能手机。用这种方式使用手机按键是一个非常聪明的主意。如果用户是问题所在。。。教育用户。@ElzoValugi:我想这是一个态度问题。我个人认为,我的用户可能遇到的问题是我的问题,而不是他们的问题。我认为这是一个系统问题。驱动程序是系统的一部分,系统内的通信基于规则,有些规则比其他规则更严格。但是,这些工具的目的是有效地传达一些信息,它们必须根据现有的通信标准履行自己的职责。否则,就会出现无政府状态,他们甚至会决定发送莎士比亚语录而不是D123456信息。这对我来说是一个很好的答案。我将稍微调整preg_replace模式,以涵盖我所看到的其他一些操作。
Array
(
    [status] => P
    [loadId] => 123456-3
)
Array
(
    [status] => D
    [loadId] => 456789-1
)
Array
(
    [status] => D
    [loadId] => 456789-1
)
Array
(
    [status] => D
    [loadId] => 456789-1
)