0

我有一个与这篇文章中回答的问题类似的问题。

当我测试作为该帖子中答案提供的正则表达式时,它按预期工作:

  $str = 'Days - £9.20 to £11.20 Sat - £11.80 Sun - £13.30';            

  preg_match_all("/£\s*\d+(?:\.\d+)?/", $str, $matches);                    

  print_r($matches);

  // Produces
  Array
  (
     [0] => Array
        (
          [0] => £9.20
          [1] => £10.20
          [2] => £11.80
         )
   )

当我尝试使用它来处理来自我已在 foreach 循环中转换为数组的 CSV 数据时,问题就出现了:

foreach($arrJobs as $job)
{
    $str = $job['payDetails1'] . ' ' . $job['payDetails2'];                     

    // Try to find salary from string           

    preg_match_all("/£\s*\d+(?:\.\d+)?/", $str, $matches);

    print_r($matches);                  
}

// In this example the output from every item is an empty array:

 Array
 (
   [0] => Array
       (
       )

  )

我在第一个示例中用于测试函数的字符串是通过在第二个示例中回显 $str 的值并复制和粘贴它来获得的。

我不明白为什么相同的字符串会返回不同的结果?为什么当我将字符串粘贴到变量中时它可以正常工作,但是从 CSV 中检索字符串时却找不到匹配项?

4

1 回答 1

1

[答案来自上面的评论和反馈]

问题

这里的问题是您的源文件和 CSV 输入未使用相同的字符编码保存。

PHP 中的所有内置字符串函数(包括/u不使用标志时的 PCRE 函数)都对字节序列进行盲目操作,并且不能识别字符本身。这意味着对于包含 ASCII 范围之外的字符的脚本,运行时行为将根据脚本保存在哪种编码中而改变,因为对于实践中使用的每种编码,这些字符将转换为不同的字节。您的脚本包含一个这样的字符:井号

快速解决方案

假设此处可能使用的编码是ISO 8859-1 (Western European)UTF-8,则与正则表达式匹配的所有剩余字符在两种编码中都具有相同的表示形式,因此它们不会出现问题。那么让我们看看我们可以对英镑符号做些什么。

通常,您可以通过将文字替换为£涵盖所有字符编码的交替组来解决此问题。

        POUND SIGN ( £ )
when encoded in    is represented as
------------------------------------
ISO 8859-1         0xA3
UTF-8              0xC2 0xA3

因此,(\xa3|\xc2\xa3)第一部分涵盖 ISO 8859-1 和第二部分 UTF-8。但是,也可以看到两个部分以\xa3相同的结果结尾\xc2?\xa3(使\xc2前缀可选)。

因此,您可以通过将代码更改为

preg_match_all('/\xc2?\xa3\s*\d+(?:\.\d+)?/', $str, $matches);

更好的解决方案

然而,最好的解决方案是始终使用 UTF-8。为此,您需要

  1. 将脚本另存为 UTF-8
  2. 确保输入 CSV 以 UTF-8 开头,或者在处理之前将其转换为 UTF-8(您可以使用它iconv来执行此操作)

这样,您可以返回在脚本中保存文字井号,并且仍然可以安全地知道,无论 CSV 数据的输入编码是什么,它都能正常工作。

于 2012-09-25T10:23:12.070 回答