Sed替换<! - ?与<?php

时间:2016-11-15 21:32:39

标签: php regex sed

我有一些需要在较新的服务器上运行的真正的旧代码(php 5.1)。

新服务器有PHP 5.6,所以

的任何区域
<?

用于打开PHP上下文,这些没有被正确解释。我需要替换

的所有实例
<?

<?php

除了其中

<?

已经是

的一部分
<?php

我的初衷是使用反向引用和sed:

cat file.php | sed -i 's/<?([^php])/<?php\$1/g'

然而,()似乎打破了比赛,没有它,我就没有合适的后退参考。

我试图在 PHP开启标签之后将的任何内容放到反向引用中,所以我可以改为:

<?=$_COOKIE...

<?php=$_COOKIE...

而且,请不要指我:Using sed to replace <? with <?php。我已经看过了,并没有解决这个问题,即我已经在某些地方拥有了新的开放标签而在其他地方已经有了旧标签。 (答案之一就是这样,但我宁愿不创建“phpphphphpphp”并且必须一遍又一遍地搜索它以将其减少为“php”

最后,请原谅奇怪间隔的开启和关闭标签。只有当它们在代码块中时,才能显示它们与文本一致。

2 个答案:

答案 0 :(得分:2)

你可以这样做:

sed 's/<?\(php\)*/<?php/g' file

在这种情况下&#34; php&#34;是可选的,但如果它已经在这里,则会被系统地覆盖。

或者使用白色空间字符作为AbraCadaver的建议,因为它似乎是在短标签后强制使用的:

sed 's/<?\([[:space:]]\)/<?php\1/g' file

限制:此模式无法知道<?<?php是否在字符串中。例如:

echo 'abc <? def';

变为:

echo 'abc <?php def';

更好的方法是将PHP本身与tokenizer一起使用。

示例:

$str = 'echo "blah"; <? echo "sblub"; ?> bluh';

$result = '';

foreach(token_get_all($str) as $tok) {
    $result .= ($tok[0] == 376) ? '<?php' : $tok[1]; 
}

echo $result;

答案 1 :(得分:0)

你可以试试这个 https://regex101.com/r/tMkwCT/1

正则表达式:

^<\?([^p\=])/gm  

替换:

<?php$1  

说明:
^断言行开头的位置
&LT;匹配字符&lt;字面意思(区分大小写)
\?匹配角色?字面意思(区分大小写)
第一捕获组([^ p \ =])
匹配下面列表中不存在的单个字符[^ p \ =]
p字符匹配字符p(区分大小写)
\ =匹配字符=字面意思(区分大小写)
全球模式标志
g修饰符:全局。所有比赛(首场比赛后不返回)
m修饰符:多行。导致^和$匹配每行的开头/结尾(不仅是字符串的开头/结尾)

您可以修改SED脚本

或者您可以启用short_open_tag http://php.net/manual/en/language.basic-syntax.phptags.php

PHP also allows for short open tag <? (which is discouraged since it is only available if enabled using the short_open_tag php.ini configuration file directive, or if PHP was configured with the --enable-short-tags option).

更新:
- https://regex101.com/r/tMkwCT/4来自@SamuelAialaFerreira
- https://regex101.com/r/tMkwCT/7 - 删除^以便检查开头代码是否不在行的开头