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
       (
       )

  )

最初の例で関数をテストするために使用した文字列は、2 番目の例で $str の値をエコーアウトし、それをコピーして貼り付けることによって得られました。

同じ文字列が異なる結果を返す理由がわかりません。また、文字列を変数に貼り付けると正常に動作するのに、CSV から文字列を取得すると一致が見つからないのはなぜですか?

4

1 に答える 1

1

[上記のコメントとフィードバックから得られた回答]

問題

ここでの問題は、ソース ファイルと CSV 入力が同じ文字エンコードで保存されていないことです。

PHP に組み込まれているすべての文字列関数 (/uフラグが使用されていない場合の PCRE 関数を含む) は、バイト シーケンスに対して盲目的に動作し、文字自体を認識しません。これは、ASCII 範囲外の文字を含むスクリプトの場合、スクリプトが保存されているエンコーディングに応じて実行時の動作が変わることを意味します。これらの文字は、実際に使用されるエンコーディングごとに異なる方法でバイトに変換されるためです。スクリプトには、そのような文字が 1 つ含まれています:シャープ記号.

迅速な解決策

ここで考えられるエンコーディングがISO 8859-1 (西ヨーロッパ)UTF-8であると仮定すると、正規表現に一致する残りのすべての文字は両方のエンコーディングで同じ表現を持つため、問題はありません。それでは、ポンド記号について何ができるか見てみましょう。

£通常、この問題は、文字のすべてのエンコーディングをカバーする代替グループでリテラルを置き換えることによって解決します。

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

つまり(\xa3|\xc2\xa3)、最初の部分は ISO 8859-1 をカバーし、2 番目の部分は 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 に答える