【问题标题】:Regex to extract multiple substrings from strings with a predictable format正则表达式从具有可预测格式的字符串中提取多个子字符串
【发布时间】:2018-11-26 00:40:35
【问题描述】:

我在下面得到了这个字符串。

string(49) "02/12/2018 (Assessment 2) = /86= | Weight: 50.00%"
string(49) "02/12/2018 (Assessment 2) = 50.83/86= | Weight: 50.00%""

第一个例子在/之前没有显示任何数字,在这种情况下我需要使用00.00作为默认值。

我需要获取这些信息并放入一个像这样的数组中:

$dados[ "date" ] = "02/12/2018"
$dados[ "markOK" ] = "50"
$dados[ "markTotal" ] = "86"
$dados[ "weight" ] = "50.00"

其他例子:

string(49) "02/12/2018 (Assessment 2) = /86= | Weight: 50.00%"
string(59) "06/11/2018 (Assessment 2) = 22.40/35=32.00 | Weight: 50.00%"
string(49) "04/12/2018 (Assessment 2) = /60= | Weight: 50.00%"
string(59) "11/09/2018 (Assessment 2) = 27.00/40=33.75 | Weight: 50.00%"
string(59) "09/09/2018 (Assessment 2) = 30.00/30=50.00 | Weight: 50.00%"
string(59) "14/08/2018 (Assessment 2) = 31.00/40=38.75 | Weight: 50.00%"
string(59) "19/06/2018 (Assessment 2) = 63.00/72=43.75 | Weight: 50.00%"
string(59) "17/06/2018 (Assessment 2) = 45.00/45=50.00 | Weight: 50.00%"
string(59) "22/05/2018 (Assessment 2) = 11.00/55=10.00 | Weight: 50.00%"

【问题讨论】:

  • 即使不熟悉正则表达式,您也应该能够描述您打算如何提取字符串部分。如➊首先是数字+正斜杠的混合,➋然后找到第一个=,➌获取句号或正斜杠之前的数字,➍斜杠之后的数字,➎和文字Weight:␣之后的数字部分。一旦你把它写成这样的话,正则表达式通常会自己写。
  • 这个问题似乎根本没有包括任何解决问题的尝试。 StackOverflow 期待您try to solve your own problem first,因为您的尝试有助于我们更好地了解您想要什么。请编辑问题以显示您尝试过的内容,并使用Minimal, Complete, and Verifiable example 显示您遇到的特定障碍。欲了解更多信息,请参阅How to Ask

标签: php regex string


【解决方案1】:

像这样:

(?P<date>\d{2}\/\d{2}\/\d{4})[^=]+=\s(?P<markOK>\d+(?:\.\d+)?)?\/(?P<markTotal>\d+)[^:]+:\s(?P<weight>\d+(?:\.\d+)?)

Test online

其实很简单。

  • (?P&lt;date&gt;\d{2}\/\d{2}\/\d{4})抓拍日期
  • [^=]+=\s 跳过所有不等于然后等于和空格的内容
  • (?P&lt;markOK&gt;\d+(?:\.\d+)?)? 捕获浮点数(可选)
  • \/斜线
  • (?P&lt;markTotal&gt;\d+)捕获整数
  • [^:]+:\s 跳过所有内容,不是冒号,而是冒号和空格
  • (?P&lt;weight&gt;\d+(?:\.\d+)?)捕获浮动

更新

$pattern = '/(?P<date>\d{2}\/\d{2}\/\d{4})[^=]+=\s(?P<markOK>\d+(?:\.\d+)?)?\/(?P<markTotal>\d+)[^:]+:\s(?P<weight>\d+(?:\.\d+)?)/';
if(preg_match($pattern, $str, $matches)){
   var_export($matches);
}

如果你想清理匹配数组,你可以这样做:

$str = '04/12/2018 (Assessment 2) = /60= | Weight: 50.00%';
$pattern = '/(?P<date>\d{2}\/\d{2}\/\d{4})[^=]+=\s(?P<markOK>\d+(?:\.\d+)?)?\/(?P<markTotal>\d+)[^:]+:\s(?P<weight>\d+(?:\.\d+)?)/';
if(preg_match($pattern, $str, $matches)){
    $default = [
        'date' => '00/00/0000',
        'markOK' => '0.00',
        'markTotal' => '0',
        'weight' => '0.00'
    ];

    $matches = array_filter($matches);
    $matches = array_merge($default, array_intersect_key($matches, $default));


   var_export($matches);
}

Try it online

输出

array (
  'date' => '04/12/2018',
  'markOK' => '0.00',
  'markTotal' => '60',
  'weight' => '50.00',
)

【讨论】:

  • 它在在线站点中工作...但在代码中不起作用... $result = preg_match_all( "/(?P\d{2}\/\d{ 2}\/\d{4})[^=]+=\s(?P\d+(?:\.\d+)?)?\/(?P\d+)[^ :]+:\s(?P\d+(?:\.\d+)?)/", $contentInfo);变量转储($结果)。 "\n";
  • preg match 返回一个布尔值,尝试使用第三个参数进行匹配,参见php.net/manual/en/function.preg-match.php
  • 现在可以正常使用了 :) "markOk" 为空时有任何更改,替换为 00.00
【解决方案2】:

虽然在这种情况下使用命名的捕获组肯定是有目的的,但我发现语法会使模式不必要地臃肿且难以阅读。匹配子字符串(特别是可选的第二个子字符串)后,您需要编写一个条件以将零长度字符串替换为 00.00

以下是我的建议:

代码:(PHP Demo) (Regex Demo)

$strings = [
    "02/12/2018 (Assessment 2) = /86= | Weight: 50.00%",
    "06/11/2018 (Assessment 2) = 22.40/35=32.00 | Weight: 50.00%",
    "04/12/2018 (Assessment 2) = /60= | Weight: 50.00%",
    "11/09/2018 (Assessment 2) = 27.00/40=33.75 | Weight: 50.00%",
    "09/09/2018 (Assessment 2) = 30.00/30=50.00 | Weight: 50.00%",
    "14/08/2018 (Assessment 2) = 31.00/40=38.75 | Weight: 50.00%",
    "19/06/2018 (Assessment 2) = 63.00/72=43.75 | Weight: 50.00%",
    "17/06/2018 (Assessment 2) = 45.00/45=50.00 | Weight: 50.00%",
    "22/05/2018 (Assessment 2) = 11.00/55=10.00 | Weight: 50.00%"
];

foreach ($strings as $string) {
    if (!preg_match('~(\d\d/\d\d/\d{4})[^=]+= (\d+(?:\.\d+)?)?/(\d+)[^:]+: (\d+(?:\.\d+)?)~', $string, $m)) {
        echo "No match for string: $string\n";
    } else {
        $results[] = ['date' => $m[1], 'markOK' => strlen($m[2]) ? $m[2] : '00.00', 'markTotal' => $m[3], 'weight' => $m[4]];
    }
}
var_export($results);

输出:

array (
  0 => 
  array (
    'date' => '02/12/2018',
    'markOK' => '00.00',
    'markTotal' => '86',
    'weight' => '50.00',
  ),
  1 => 
  array (
    'date' => '06/11/2018',
    'markOK' => '22.40',
    'markTotal' => '35',
    'weight' => '50.00',
  ),
  2 => 
  array (
    'date' => '04/12/2018',
    'markOK' => '00.00',
    'markTotal' => '60',
    'weight' => '50.00',
  ),
  3 => 
  array (
    'date' => '11/09/2018',
    'markOK' => '27.00',
    'markTotal' => '40',
    'weight' => '50.00',
  ),
  4 => 
  array (
    'date' => '09/09/2018',
    'markOK' => '30.00',
    'markTotal' => '30',
    'weight' => '50.00',
  ),
  5 => 
  array (
    'date' => '14/08/2018',
    'markOK' => '31.00',
    'markTotal' => '40',
    'weight' => '50.00',
  ),
  6 => 
  array (
    'date' => '19/06/2018',
    'markOK' => '63.00',
    'markTotal' => '72',
    'weight' => '50.00',
  ),
  7 => 
  array (
    'date' => '17/06/2018',
    'markOK' => '45.00',
    'markTotal' => '45',
    'weight' => '50.00',
  ),
  8 => 
  array (
    'date' => '22/05/2018',
    'markOK' => '11.00',
    'markTotal' => '55',
    'weight' => '50.00',
  ),
)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-09
    • 2014-08-25
    • 2010-10-14
    • 2020-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多