【问题标题】:preg_match_all doesn't return a resultpreg_match_all 不返回结果
【发布时间】:2017-02-20 02:32:31
【问题描述】:

我想通过 PHP 中的正则表达式匹配将字符串解析为数据集。 这是我的代码:

$string = "?\t\t\t\t\t\t?\t\t\t\t\t\t\t\t\t\t\t\t<?xml version=\"1.0\" encoding=\"UTF-8\"?><documents><Resp><gatewayId>g10060<\/gatewayId><accountId>310198232<\/accountId><orderNo>0970980541000510490500480<\/orderNo><tId><\/tId><tAmt>20<\/tAmt><result>1<\/result><respCode>21<\/respCode><signMD5>7ecd1eb9b870aaba3bfa45892095194e<\/signMD5><\/Resp><\/documents>";
preg_match_all('/<(.*?)>(.*?)<\\/(.*?)>/', $string, $arr);
echo json_encode($arr);

但是它只返回我[[],[],[],[]],作为空数组。我在https://regex101.com/ 上尝试了正则表达式,它显示了正确的结果,但它在我的服务器上不起作用。

我想要的是:

[ "gatewayId" => "g10060",
  "accountId" => "310198232",
  "orderNo" => "0970980541000510490500480",
  "tId" => "",
  "tAmt" => "20",
  "result" => "1",
  "respCode" => "21",
  "signMD5" => "7ecd1eb9b870aaba3bfa45892095194e" ]

我该如何解决这个问题?

【问题讨论】:

  • 不要使用正则表达式:stackoverflow.com/questions/3577641/…
  • 他们给了我一种类似于xml的奇怪格式,但我不能简单地使用xml解析器
  • 那个是 xml
  • 在 xml 验证器中失败,我如何用 php 处理它?
  • 认为很明显你需要先清理逃逸。 XML 解析器仍然比使用正则表达式更好

标签: php regex preg-match-all


【解决方案1】:

用途:

<?php

$string = "?\t\t\t\t\t\t?\t\t\t\t\t\t\t\t\t\t\t\t<?xml version=\"1.0\" encoding=\"UTF-8\"?><documents><Resp><gatewayId>g10060<\/gatewayId><accountId>310198232<\/accountId><orderNo>0970980541000510490500480<\/orderNo><tId><\/tId><tAmt>20<\/tAmt><result>1<\/result><respCode>21<\/respCode><signMD5>7ecd1eb9b870aaba3bfa45892095194e<\/signMD5><\/Resp><\/documents>";
preg_match_all('#<([^\?>]+)>([^<]+)<\\\/[^>]+>#', $string, $arr);

list($_, $tags, $values)= $arr;

// As @billynoah said it's much less code
$result = array_combine($tags, $values);

/*
 * Old inefficient code commented
 *
$result = array_reduce(array_keys($tags), function($carry, $key) use ($tags, $values){
    $k = $tags[$key];
    $v = $values[$key];
    $carry[$k] = $v;
    return $carry;
},[]);
*/

var_dump($result);

结果:

array(7) {
  ["gatewayId"] => string(6) "g10060"
  ["accountId"] => string(9) "310198232"
  ["orderNo"]   => string(25) "0970980541000510490500480"
  ["tAmt"]      => string(2) "20"
  ["result"]    => string(1) "1"
  ["respCode"]  => string(2) "21"
  ["signMD5"]   => string(32) "7ecd1eb9b870aaba3bfa45892095194e"
}

【讨论】:

  • 你是对的 - 我只专注于解决斜线问题 - 这更好。
  • 我可以建议将整个array_reduce() 替换为简单的:$result = array_combine($tags,$values);
  • 哦..是的..我的错:)
  • 谢谢,这正是我需要的。
【解决方案2】:

您需要对反斜杠进行双重转义。使用非斜线分隔符也有助于提高可读性:

preg_match_all('~<(.*?)>(.*?)<\\\/(.*?)>~', $string, $arr);

【讨论】:

  • 作为记录,如果你想在这里使用/ 作为分隔符,你实际上需要为整个序列使用 5 个反斜杠:preg_match_all('/&lt;(.*?)&gt;(.*?)&lt;\\\\\/(.*?)&gt;/', $string, $arr);。这有点荒谬——因此为什么我会选择一个不同的分隔符。很高兴它有帮助。
【解决方案3】:

首先,正则表达式并不是解析 XML 字符串的最佳解决方案。我认为使用 SimpleXml 会容易得多。

$object = new SimpleXMLElement($xmlString);

我读过你的 cmets。 如果我是你,我会尝试清理 XML 并将其用作 XML .. 如果响应发生变化,你最终会通过更改正则表达式规则来循环运行。修剪、替换使其成为有效的 XML 或....也许您可以尝试直接从源获取有效的 XML

【讨论】:

  • 我的字符串中的?\t\t\t\t\t\t?\t\t\t\t\t\t\t\t\t\t\t\t 将通过使用 SimpleXMLElement 的异常。
  • 即使我删除了它,所有 &lt;\/XXXX&gt; 在 xml 验证器中仍然失败
  • @user3711105:写$xml = str_replace("\/", "/", trim($str,"? \t"));是不是太复杂了?
  • 您应该将示例扩展为一个非常简单的用例并添加代码标签,但我认为这是最好的答案。
猜你喜欢
  • 2015-10-17
  • 2016-07-03
  • 1970-01-01
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
  • 2019-06-18
  • 2020-04-05
  • 2018-03-19
相关资源
最近更新 更多