0

解决方案是研究前瞻和后瞻——RegEx 中的 LookArounds 概念帮助我解决了我的问题,因为当我进行替换时,替换被彼此吃掉了

因此,我们一直在努力对我们的一些旧项目和(可能是坏/旧的编码习惯)进行一些转换,并且正在努力使它们为 php7 做好准备。在这个过程中,我对项目的 .php 文件进行了一些调整,例如

手头的问题是,我在 php 字符串函数(strlen、substr 等)中遇到了丹麦字符的一些问题,并希望他们改用 mb_string 函数。从我可以在互联网上阅读的内容来看,使用“重载”功能不是可行的方法,因此我决定进行基于文件的搜索替换。

我的搜索替换功能现在看起来像这样(感谢@SeanBright 更新

        $testfile = file_get_contents($file);
    $array = array (    'strlen'=>'mb_strlen',
                        'strpos'=>'mb_strpos',
                        'substr'=>'mb_substr',
                        'strtolower'=>'mb_strtolower',
                        'strtoupper'=>'mb_strtoupper',
                        'substr_count'=>'mb_substr_count',
                        'split'=>'mb_split',
                        'mail'=>'mb_send_mail',
                        'ereg'=>'mb_ereg',
                        'eregi'=>'mb_eregi',
                        'strrchr' => 'mb_strrchr',
                        'strichr' => 'mb_strichr',
                        'strchr' => 'mb_strchr',
                        'strrpos' => 'mb_strrpos',
                        'strripos' => 'mb_strripos',
                        'stripos' => 'mb_stripos',
                        'stristr' => 'mb_stristr'
    );
foreach($array as $function_name => $mb_function_name){
    $search_string = '/(^|[\s\[{;(:!\=\><?.,\*\/\-\+])(?<!->)(?<!new )' . $function_name . '(?=\s?\()/i';
    $testfile = preg_replace($search_string, "$1".$mb_function_name."$2$3", $test,-1,$count);
}
print "<pre>";
print $test;

$file 包含以下内容:

<?php
print strtoupper('test');
print strtolower'test');
print substr('tester',0,1);

print astrtoupper('test');
print bstrtolower('test');
print csubstr(('tester',0,1);
print [substr('tester',0,1)];
print {substr('tester',0,1)};
    substr('test',0,1);
substr('test',0,1);
    (substr('test',0,1));
    !substr();
    if(substr()==substr()=>substr()<substr()){
        ?substr('test');
    }
    "test".substr('test');
    'asd'.substr('asd');
    'asd'.substr('asd');
    substr( substr('asdsadsadasd',0,-1),strlen("1"),strlen("100"));
    substr (substr ('Asdsadsadasd',0,-1), strlen("1"),  strlen("100"));
    substr(substr(substr('Asdsadsadasd',0,-1),0,-1), strlen("1"),   strlen("100"));
    mailafsendelse(substr('asdsadsadasd',0,-1), strlen("1"),    strlen("100"));
    mail(test);
    substr ( tester );
    substr ( tester );
    mail mail mail mail ( tester );
    $mail->mail ();
    $mail -> mail ();
    new Mail();
    new mail ();
        strlen ( tester )*strlen ( tester )+strlen ( tester )/strlen ( tester )-strlen ( tester )

;

这里的重点是实际的 php 代码不必是有效的语法。我只是想让它在不同的场景中工作

我的正则表达式问题是我无法找出这行的原因:

substr(substr(substr('Asdsadsadasd',0,-1),0,-1), strlen("1"),   strlen("100"));

不管用。第一个和第三个 substr 被正确替换,但第二个看起来像这样:

mb_substr(substr(mb_substr('Asdsadsadasd',0,-1),0,-1), mb_strlen("1"),  mb_strlen("100"));

请注意,我的搜索字符串适用于函数名称前面的各种字符,并要求函数名称后面的字符是“(”

在一个完美的世界中,我还想排除作为类方法的字符串函数,例如:$order->mail() 会发送电子邮件。我不希望将其转换为 $order->mb_send_mail()

据我了解,所有参数都是相同的,所以应该不是问题。

完整的脚本可以在这里找到 https://github.com/welrachid/phpStringToMBString

4

1 回答 1

0

问题是您用来分隔函数调用检查的某些字符正在被匹配所消耗。如果您将最后一组切换为积极的前瞻,这将解决问题:

$search_string = '/([ \[{\n\t\r;(:!=><?\.,])'.($function_name).'([\ |\t]{0,1})(?=[(]{1})/i';
                                                                               ^^ Add these

您当前的表达式也不会匹配行首的函数调用。以下处理该问题并简化了一些事情:

$search_string = '/(^|[\s\[{;(:!=><?.,])' . $function_name . '(?=\s?\()/i';

在 regex101.com 上设置了一个示例

你甚至可以逃脱:

$search_string = '/(^|\W)' . $function_name . '(?=\s?\()/i';

where\W将匹配非单词字符。

更新

为了防止匹配的方法调用,你可以在你的模式中添加一个否定的lookbehind:

$search_string = '/(^|[\s\[{;(:!=><?.,])(?<!->)' . $function_name . '(?=\s?\()/i';
                                        ^^^^^^^
于 2018-07-19T18:01:54.163 回答