PHP的strlen()
函数不支持UTF-8,因此我想将strlen()
的每个用法与其UTF-8识别对应项交换:mb_strlen()
。但是,mb_strlen()
需要一个额外的参数:
$length = strlen($someString);
$length = mb_strlen($someString, 'UTF-8');
如果没有第二个参数,一个简单的Perl正则表达式将处理交换:
$ find . -name '*' -print0 | xargs -0 perl -pi -e 's/strlen/mb_strlen/g'
我尝试使用捕获组和反向引用,但VIM风格的语法要么不支持(在最近的Ubuntu上),要么我无法弄明白。我已经尝试了几种变体而没有成功:
$ find . -name '*' -print0 | xargs -0 perl -pi -e 's/strlen\((\.*)\)/mb_strlen\($1, "UTF-8"\)/g'
此外,trim()
内部可能存在strlen()
等函数,所以我必须让这个贪婪,但我不确定贪婪的运算符应该在哪里。这个正则表达式应该如何编写?
答案 0 :(得分:1)
这比首次出现时更难。你要么:
我会去作弊。
大多数strlen()调用都非常简单,剩下的少数几个可以手动替换。你在某种版本控制下做这件事,不是你:
简单:strlen(“foo”),strlen($ bar)
# Match simple quoted strings - no embedded quotes
s/strlen\((["'][^"']*["'])\)/mb_strlen($1, 'UTF-8')/g
# Match simple variables - no method calls etc
s/strlen\((\$\w+)\)/mb_strlen($1, 'UTF-8')/g
处理数组变量,函数和方法调用以及其他表达式变得更复杂,但是看看在这两个基本替换后剩下多少个。
答案 1 :(得分:0)
通过指定\.*
,正则表达式将匹配0个或更多文字'.'
。
省略\
:
s/strlen\((.*)\)/mb_strlen($1, "UTF-8")/g
^ ^ ^
NO BACKSLASH NO BACKSLASH NEEDED
AS THIS IS TREATED AS
A STRING AND NOT A REGEX
另外,首先尝试不使用-i
标记进行测试,以确保您对替换感到满意,否则您的文件将在原位进行修改。
答案 2 :(得分:0)
在一般情况下使用简单的正则表达式无法解决您的问题。请考虑以下示例:
if (strlen($var) > 0)
$total_length = strlen($thing1) + strlen($thing2);
strlen($var); #Don't use trim() here because it was already trimmed.
some_other_function(strlen($foo) + 2);
这些都不适用于你的正则表达式,因为.*
将贪婪地捕获所有内容直到行中的最后一个右括号。正确执行此操作的唯一方法是检查平衡括号,这在正则表达式中是非常重要的(尽管在技术上可以使用Perl的扩展正则表达式功能,但这并非易事)。
如果您认为上述情况不会遇到很多情况,那么只需使用其他建议的解决方案之一并检查错误。或者你可以这样做来捕获其中没有任何括号的所有简单案例:
s/\bstrlen\(([^()]*)\)/mb_strlen($1, "UTF-8")/g
(注意,我还添加了\b
以确保它从单词边界开始。这将阻止您双重替换已经mb_strlen
的内容
但是,有一个简单快速的黑客解决方案应该适用于所有情况:创建自己的PHP函数my_mb_strlen
,或者其他什么,在添加时调用mb_strlen
附加论点。然后,您可以执行更简单的搜索并仅替换函数名称,将strlen
替换为my_mb_strlen
。
答案 3 :(得分:0)
find . -type f|xargs perl -pi -e 's/strlen\(([^\)]*)\)/mb_strlen($1,'UTF_8')/g'