【问题标题】:How to extract substrings that follow specific keywords in a string?如何提取字符串中特定关键字之后的子字符串?
【发布时间】:2018-07-17 14:12:11
【问题描述】:

我需要处理具有大部分常规格式/结构的字符串。基本上,该字符串包含 3 个始终以相同顺序出现的关键字:ATLPáscoaATLNatalATLVerão

在这些关键字之间是未知数量的空白字符。此外,每个关键字后面都有可能包含一个可能包含非空白字符和空白字符的日期值。

通过它们的关键字关联,我想声明 3 个变量,称为 $datePáscoa$dateNatal$dateVerão,并将日期子字符串分配给这些变量。

这是一个例子:

$string = 'ATLPáscoa            ATLNatal          ATLVerão     Turno11-03a07desetembro';

我想要的输出是:

$datePáscoa = '';
$dateNatal = '';
$dateVerão = 'Turno11-03a07desetembro';

这是另一个例子:

$string = 'ATLPáscoa  bananas   ATLNatal xyza sd af          ATLVerão      Turno11-03a07desetembro';

我的预期输出是:

$datePáscoa = 'bananas';
$dateNatal = 'xyza sd af';
$dateVerão = 'Turno11-03a07desetembro';

我尝试使用str_replace(),但显然不是这样:

$string = str_replace("Atelier","",$string );
$string = str_replace("Páscoa","",$string );
$string = str_replace("Natal","",$string );
$string = str_replace("Verão","",$string );

如何提取日期值并将值分配给适当的变量?

【问题讨论】:

标签: php string substring


【解决方案1】:

代码:(Demo <- with an alternative input string)

$string = 'ATLPáscoa  banana   ATLNatal xyza sd af          ATLVerão      Turno11-03a07desetembro';

$datePáscoa = preg_match('~ATLPáscoa\s*\K(?!ATL)\S+(?:\s+(?!ATL)\S+)*~u', $string, $out) ? $out[0] : '';
$dateNatal = preg_match('~ATLNatal\s*\K(?!ATL)\S+(?:\s+(?!ATL)\S+)*~u', $string, $out) ? $out[0] : '';
$dateVerão = preg_match('~ATLVerão\s*\K\S+(?:\s+\S+)*~u', $string, $out) ? $out[0] : '';

echo '$datePáscoa = '; var_export($datePáscoa); echo "\n";
echo '$dateNatal = '; var_export($dateNatal); echo "\n";
echo '$dateVerão = '; var_export($dateVerão);

输出:

$datePáscoa = 'banana'
$dateNatal = 'xyza sd af'
$dateVerão = 'Turno11-03a07desetembro'

如果这是我的项目,我可能会构建一个单一的正则表达式函数调用,它返回数组中的所有匹配项,然后我会在需要时提取我想要的内容。您已经要求单独命名的变量,所以我认为 3 个函数调用将是最简单的演示。

您提供的输入不需要包含 u 模式修饰符,但我会添加它以防您的实际数据需要它。

\K 告诉正则表达式引擎从完整字符串匹配中“释放以前匹配的字符”——这用于避免使用捕获组并确保您的返回值只是“白肉”。相同的原因是您看到\S+(?:\s+\S+)* 的原因——它匹配一个“单词”,然后可选地匹配一个或多个空格,后跟另一个“单词”。

我在演示中使用var_export() 来表明结果中没有前导或尾随空白字符。

(?!ATL) 在前两个模式中用于避免“过度匹配”或基本上“匹配太远”。第三种模式不需要这种考虑。

【讨论】:

  • @mickmacksusa 这应该可以工作,但由于某种原因它没有检测到“ATLPáscoa”和“ATLVerão”,因为我从数据库中获取字符串,它可能有一些其他类型的特殊字符,看起来像“Páscoa”中的“á”和“Verão”中的“ã”,我在使用 string_replace 时也遇到了这个问题。
  • 我认为你的怀疑是正确的。确保将数据库中的这些字符直接复制到代码中,以确保您编写的是准确的 unicode 字符。 p.s.我从不在变量名中使用重音字母——它只会让输入变得困难,但这是我个人的偏好。当然,这个链接可能是相关的:stackoverflow.com/q/279170/2943403
  • 我正在使用这个“$string = $query->dates;”不是直接复制吗?
  • 我不是这个意思。我的意思是从您的数据库中复制 PáscoaATLVerão,然后将其粘贴到我建议的模式中,以确保使用的正是预期的字符。
  • 我应该怎么做,从 phpMyAdmin 复制?
【解决方案2】:

好吧,既然 ATL 在每个部分中,我会从一个爆炸开始:

$array = explode("ATL", $string);

请注意 $array[0] 将是一个空字符串(在这种情况下,但正如我所见,您每次都会得到相同类型的输入),然后像这样修剪前导和尾随空格:

for ( $i = 0; $i < count($array); $i++ ) {
 trim($array[$i]);
}

然后复制到各自的变量中:

$datePáscoa = $array[1];
$dateNatal = $array[2];
$dateVerão = $array[3];

此时,它们仍然包含它们的名称,因此我们使用 strpos()(返回特定字符串的位置)和 strstr()(从给定指针返回字符串的一部分)的组合来剪切它,比如:

$datePáscoa = strstr($datePáscoa,strpos($datePáscoa," ")+1);

那是一个空格。之后可能会再次修剪它们,因为它们可能在 strstr 之后仍然包含一些空格。

【讨论】:

  • 我曾想过这个选项,但由于有可能有或没有日期,并且在它们之间有空格,因此爆炸不会一直具有相同的值。示例:'ATLPáscoa ATLNatal xyza sd af ATLVerão' $array[1]= Páscoa; $array[2]= 纳塔尔; $array[3]=xyza;这意味着日期不会一直处于同一位置。
  • 我通常只使用带 " " 的爆炸,所以在这种情况下是 $array[1]= Páscoa; $array[2]= 纳塔尔 xyza sd; $array[3]= Verão;" 对吗?
  • 但是你为什么要这样做呢?我明确表示将explode与“ATL”一起使用,当整个事物都充满空格时,将其与空格一起使用是没有用的... -.-'
  • 我将它与“ATL”一起使用,我说我不理解“ATL”,因为我通常将爆炸与“”一起使用,这就是为什么我不明白它是如何工作的案例。
猜你喜欢
  • 2022-08-10
  • 2012-09-16
  • 2021-10-30
  • 1970-01-01
  • 2022-11-10
  • 1970-01-01
  • 2019-07-08
相关资源
最近更新 更多