考虑以下数组,其中包含按长度排序的所有美国股票代码:
$tickers = array('AAPL', 'AA', 'BRK.A', 'BRK.B', 'BAE', 'BA'); // etc...
我想检查所有可能匹配的字符串。代码编写时带有或不带有“$”连接到前面:
$string = "Check out $AAPL and BRK.A, BA and BAE.B - all going up!";
所有代码都标记为:{TICKER:XX}。预期的输出是:
Check out {TICKER:AAPL} and {TICKER:BRK.A} and BAE.B - all going up!
因此,应该根据$ tickers数组检查代码,如果后跟空格或逗号,则匹配两者。到现在为止,我一直在使用以下内容:
preg_replace('/\$([a-zA-Z.]+)/', ' {TICKER:$1} ', $string);
所以我没有检查$ tickers数组。假设所有代码都以“$”开头,但这只是大约80%的情况下的惯例。因此,需要更新过滤器。
我的问题是:是否有一种简单的方法来调整正则表达式以符合新要求,或者我需要编写一个新函数,正如我先计划的那样:
function match_tickers($string) {
foreach ($tickers as $ticker) {
// preg_replace with $
// preg_replace without $
}
}
或者这可以一次完成吗?
答案 0 :(得分:2)
使用?
(零或1个匹配),只需将前导美元符号设为可选。然后,您可以使用相同的技术检查合法的尾随字符。更好的方法是explode
输入字符串,并根据自动收录器集合检查/替换每个子字符串,然后重构输入字符串。
function match_tickers($string) {
$aray = explode( " ", $string );
foreach ($aray as $word) {
// extract any ticker symbol
$symbol = preg_replace( '/^\$?([A-Za-z]?\.?[A-Za-z])\W*$/', '$1', $word );
if (in_array($symbol,$tickers)) { // symbol, replace it
array_push( $replacements, preg_replace( '/^\$?([A-Za-z]?\.?[A-Za-z])(\W*)$/', '{TICKER:$1}$2', $word ) );
}
else { // not a symbol, just output it normally
array_push( $replacements, $word );
}
}
return implode( " ", $replacements );
}
答案 1 :(得分:1)
我认为只需对你的正则表达式进行一些改动即可:
\$?([a-zA-Z.]+)
我加了“?”在“$”前面,这意味着它可以出现0或1次
答案 2 :(得分:1)
您可以在阵列上使用单个foreach循环来替换字符串中的自动收录器项。
$tickers = array('AAPL', 'AA', 'BRK.A', 'BRK.B', 'BAE', 'BA');
$string = 'Check out $AAPL and BRK.A, BA and BAE.B - all going up!';
foreach ($tickers as $ticker) {
$string = preg_replace('/(\$?)\b('.$ticker.')\b(?!\.[A-Z])/', '{TICKER:$2}', $string);
}
echo $string;
将输出
查看{TICKER:AAPL}和{TICKER:BRK.A},{TICKER:BA}和BAE.B - 一切都在上升!
答案 3 :(得分:0)
在?
符号后添加$
也会接受单词,即'out'
preg_replace接受数组作为模式,因此如果将$ tickers数组更改为:
$tickers = array('/AAPL/', '/AA/', '/BRK.A/', '/BRK.B/', '/BAE/', '/BA/');
然后这应该做的伎俩:
preg_replace($tickers, ' {TICKER:$1} ', $string);