【问题标题】:preg_replace or preg_match and how can i define it rightpreg_replace 或 preg_match 以及如何正确定义它
【发布时间】:2016-05-23 20:58:43
【问题描述】:

这是我的字符串:

$string =  "format,surcharge,amount,1,card,basicprice 3,50  F010F020,0%,3,50 ,,,";

我想要一个应该如下所示的数组:

array(
    0 => "format",
    1 => "surcharge",
    2 => "amount",
    3 => "1",
    4 => "card",
    5 => "basicprice",
    6 => "3,50",          //<-- tricky part, i complete don't get how i can solve this
    7 => "card",
    8 => "F010",          //<-- tricky part, i complete don't get how i can solve this   
    9 => "F020",          //<-- tricky part, i complete don't get how i can solve this
    10 => "3,50",
);

所以我的尝试看起来像这样:

$string =  "Format,Aufpreis,Anzahl,1,Card,Basispreis 3,50  F010F020,0%,3,50 ,,,,,,";
$regEx = '/,/';
$replace = ' ';
$perfectArray = preg_replace('/,/', $replace, $string2);
var_dump($perfectArray);

或者像这样

$array = str_split($string);

$from = array(",", '"');
$to = array(" ", " ");

    foreach ($array as $value)
    {
        $value = str_replace($from, $to, $string);
    }
    var_dump($value);

有人知道我该如何解决这个问题吗?尤其是“棘手的部分”(我在代码中添加了注释)

如果有人能回答会很好:)

【问题讨论】:

  • 什么决定了F010是一个项目?是G999还是ä9A90?你必须在你的问题中定义这个。您希望 "card" 以什么逻辑出现在 "3,50" 数组中?
  • 您无法通过替换(即使进行大量测试)来真正解决此类问题。如果可能的话,最好的方法是知道每个字段应该包含什么,并用捕获组以preg_match 的模式描述整行。 (主要思想是描述每个字段的格式)
  • 您可以尝试preg_splitregex like this 是否会覆盖您的输入。 Here's a demo at eval.in
  • 似乎该字符串是某些 csv 的一部分,是这样吗?如果是,您确定数据类似于 ,basicprice 3,50 F010F020, 吗?它不是像,"basicprice 3,50 F010F020", 这样的引用本身吗?问这个是因为如果 csv 中的字段本身包含逗号,那么它通常在引号内。
  • @aikn,如果带有正则表达式的 preg_split 可以满足您可能拥有的所有类型数据的需求,那么请继续使用它。我提到了一些 csv 函数的使用,因为这将使您的生活更轻松,因为在字段之间出现的“,”(我知道 , 是一个小数,就像在欧洲的某些地方发生的那样)

标签: php regex preg-replace str-replace


【解决方案1】:

在你在 cmets 中提到你有 CSV 格式的原始数据之后,使用正则表达式并不是最好的解决方案。

而是使用 PHP 的 CSV 函数将数据拆分为一个数组,例如 str_getcsv:

$csv = 'F251,43%,"3,50 €","0,50 €","0,50 €",,"0,50 €","0,50 €","0,50 €","0,49 €",
        "0,49 €",,"0,47 €",,"0,47 €",,"0,46 €","0,46 €","0,44 €","0,44 €","0,44 €",,
        "0,43 €",,"0,43 €","0,43 €",,,"0,41 €",,,"0,40 €","0,40 €",,"0,39 €",
        "0,39 €",,"0,37 €","0,37 €","0,36 €","0,36 €","0,36 €","0,36 €","0,36 €"';

$data = str_getcsv($csv);

var_export ($data);

输出:

array (
  0 => 'F251',
  1 => '43%',
  2 => '3,50 €',
  3 => '0,50 €',
  4 => '0,50 €',
  5 => '',
  6 => '0,50 €',
  7 => '0,50 €',
  8 => '0,50 €',
  9 => '0,49 €',
  10 => '0,49 €',
  11 => '',
  12 => '0,47 €',
  13 => '',
  14 => '0,47 €',
  15 => '',
  16 => '0,46 €',
  17 => '0,46 €',
  18 => '0,44 €',
  19 => '0,44 €',
  20 => '0,44 €',
  21 => '',
  22 => '0,43 €',
  23 => '',
  24 => '0,43 €',
  25 => '0,43 €',
  26 => '',
  27 => '',
  28 => '0,41 €',
  29 => '',
  30 => '',
  31 => '0,40 €',
  32 => '0,40 €',
  33 => '',
  34 => '0,39 €',
  35 => '0,39 €',
  36 => '',
  37 => '0,37 €',
  38 => '0,37 €',
  39 => '0,36 €',
  40 => '0,36 €',
  41 => '0,36 €',
  42 => '0,36 €',
  43 => '0,36 €',
)

如果您想去掉 % 符号,和/或使用小数点作为数字(以便在 PHP 中进行进一步计算),那么您可以这样做:

$data = array_map(function ($v) { 
    // get rid of `€` or `%` at the end of values:
    $v = preg_replace('/( €|%)$/', '', $v);
    // if you want to replace the decimal comma to point for further calculations:
    $num = str_replace(',', '.', str_replace('.', '', $v));
    return is_numeric($num) ? $num : $v;
}, $data);

var_export ($data);

哪些输出:

array (
  0 => 'F251',
  1 => '43',
  2 => '3.50',
  3 => '0.50',
  4 => '0.50',
  5 => '',
  6 => '0.50',
  7 => '0.50',
  8 => '0.50',
  9 => '0.49',
  10 => '0.49',
  11 => '',
  12 => '0.47',
  13 => '',
  14 => '0.47',
  15 => '',
  16 => '0.46',
  17 => '0.46',
  18 => '0.44',
  19 => '0.44',
  20 => '0.44',
  21 => '',
  22 => '0.43',
  23 => '',
  24 => '0.43',
  25 => '0.43',
  26 => '',
  27 => '',
  28 => '0.41',
  29 => '',
  30 => '',
  31 => '0.40',
  32 => '0.40',
  33 => '',
  34 => '0.39',
  35 => '0.39',
  36 => '',
  37 => '0.37',
  38 => '0.37',
  39 => '0.36',
  40 => '0.36',
  41 => '0.36',
  42 => '0.36',
  43 => '0.36',
)

基于正则表达式的原始答案

您可以使用正则表达式来执行此操作,但这取决于您拆分其他字符串的规则。此正则表达式假定字符串将始终以相同的顺序具有相同数量的项目,并且关于 F010F020 它假定它们始终占据恰好 4 个字符并且始终存在:

$string = "format,surcharge,amount,1,card,basicprice 3,50  F010F020,0%,3,50 ,,,";

preg_match("/(.*?),(.*?),(.*?),(.*?),(.*?),(.*?)\s+(.*?)\s+(.{4})(.{4}),(.*?),(\d+,\d\d)\s/",
    $string, $matches);

var_export ($matches);

这个输出:

array (
  0 => 'format,surcharge,amount,1,card,basicprice 3,50  F010F020,0%,3,50 ',
  1 => 'format',
  2 => 'surcharge',
  3 => 'amount',
  4 => '1',
  5 => 'card',
  6 => 'basicprice',
  7 => '3,50',
  8 => 'F010',
  9 => 'F020',
  10 => '0%',
  11 => '3,50',
)

【讨论】:

  • 对不起,我认为我的问题做错了,但感谢您的回答,现在我对正则表达式的工作原理有了更好的了解。所以我得到一个看起来像这样的 csv(但更长): €","0,82 €" F081,20%,"3,50 €","3,00 €","2,40 €" 和当然谢谢你:)
  • 我更新了我的答案,使用您在源头拥有 CSV 数据的新信息。直接处理 CSV 比使用正则表达式要好得多。
【解决方案2】:

正如您的 cmets 中所述,如果这是来自 csv,请尝试使用

fgetcsv 函数。

您可以直接处理这些值。

看这里http://php.net/manual/en/function.fgetcsv.php,例子解释得很好

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-08
    • 2020-03-17
    相关资源
    最近更新 更多