我有一个字符串,如下所示:
$str ="it is a test string.";
// for more clarification
i t i s a t e s t s t r i n g .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Run Code Online (Sandbox Code Playgroud)
现在我需要检查所有4的倍数(加上第一个字符)的字符.像这些:
1 => i
4 => i
8 => [space]
12 => t
16 => r
20 => .
Run Code Online (Sandbox Code Playgroud)
现在,我需要将它们与Y (Y它是变量(符号))Y = 'r'进行比较,例如在这里.所以我想替换Y为X(X也是一个变量(符号),例如X = 'm'在这里).
所以,我想要这个输出:
it is a test stming.
Run Code Online (Sandbox Code Playgroud)
这是我的解决方案:我可以使用一些PHP函数来做到这一点:
strlen($str):计算字符数(命名$sum)$sum / 4:查找4的倍数的字符substr($str, 4,1):选择特定字符(命名$char) { 问题在这里}if ($char == 'r') {}: 比较str_replace('r','m',$char): 取代然后将所有内容$char相互结合.
但我的解决方案有两个问题:
substr()不计算[space]字符(如上所述)那么,有什么解决方案吗?我喜欢用REGEX做到这一点,有可能吗?
bob*_*ble 10
可以只使用一个简单的正则表达式与回调(补充u 修改如果UTF-8,s为.配合新行).
$str = preg_replace_callback(['/^./', '/.{3}\K./'], function ($m) {
return $m[0] == "r" ? "m" : $m[0];
}, $str); echo $str;
Run Code Online (Sandbox Code Playgroud)
这是一次测试.
^.任何第一个角色\K在.{3}任意三个字符后重置,只想检查第四个.要与匿名函数一起使用,需要PHP> = 5.3.这是解决方法.
function cb($m) { return $m[0] == "r" ? "m" : $m[0]; }
$str = preg_replace_callback(['/^./', '/.{3}\K./'], 'cb', $str);
Run Code Online (Sandbox Code Playgroud)
如果字符串中的所有字符都是单字节,则可以使用PHP的官方语言参考:
$str ="it is a test string.";
$y="r";
$x="m";
$len=strlen($str);
if($str[0]==$y)
{
$str=substr_replace($str,$x,0,1);
}
if($len>=3)
{
for($i=3;$i<$len;$i+=4)
{
if($str[$i]==$y)
{
$str=substr_replace($str,$x,$i,1);
}
}
}
var_dump($str);
Run Code Online (Sandbox Code Playgroud)
输出 it is a test stming.
编辑:
正如@DissPanic指出的那样,String是可变的使用[]运算符,所以而不是使用
$str=substr_replace($str,$x,$i,1);
Run Code Online (Sandbox Code Playgroud)
你可以使用
$str[$i]=$x;
Run Code Online (Sandbox Code Playgroud)
尝试这个
$str ="it is a test string.";
$y="r";
$x="m";
$splite_array = str_split($str);
foreach ($splite_array as $key => $val)
{
if($key % 4 == 0 && $val == $y)
{
$splite_array[$key] = $x;
}
}
$yout_new_string = implode($splite_array);
Run Code Online (Sandbox Code Playgroud)
这是使用preg_replace()的替代方法
$y = 'r';
$y = preg_quote($y, '/');
$x = 'M';
$x = preg_quote($x, '/');
$subject = 'rrrrrr rrrrr rrrrrr rrrr rrrr.';
$regex = "/\\G(?:^|(?(?<!^.).)..(?:.{4})*?)\\K$y/s";
$result = preg_replace($regex, $x, $subject);
echo $result;
// => MrrMrr MrrrM rrMrrr rrrM rrMr.
Run Code Online (Sandbox Code Playgroud)
正则表达式:
\G(?:^|(?(?<!^.).)..(?:.{4})*?)\Km
Run Code Online (Sandbox Code Playgroud)
\G 是最后一个匹配结束(或字符串开头)的断言(?:^|(?(?<!^.).)..(?:.{4})*?) 火柴:
^ 字符串的开头,以检查位置1(?(?<!^.).) 是一个if子句,其产生:
..(?:.{4})*?) 2个字符+ 4的倍数(如果刚在位置1处替换的话)...(?:.{4})*?) 3个字符+ 4的倍数以进行连续匹配\K 重置匹配的文本,以避免使用反向引用不过,我必须说,正则表达式对于此任务来说是一个过大的杀伤力。该代码是违反直觉的,并且是典型的正则表达式,证明难以理解/调试/维护。
编辑。稍后进行了有关性能与代码可读性的讨论,因此我做了一个基准比较:
substr_replace((@Passerby的答案)。结果:
Code #1(with_callback): 0.548 secs/50k loops
Code #2(regex_array): 0.158 secs/50k loops
Code #3(no_regex): 0.120 secs/50k loops
Code #4(pure_regex): 0.118 secs/50k loops
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
550 次 |
| 最近记录: |