用sed替换模式中的char

时间:2015-04-28 08:36:13

标签: php sed

我试图更改为使用ZF1 / PEAR约定将我的php代码迁移到命名空间。

所以我想改变

$locale_test = (new ACME_Common_Factory())->createLocale(ACME_Common_Enum_Civility::MR);

$locale_test = (new \ACME\Common\Factory())->createLocale(\ACME\Common\Enum\Civility::MR);

我尝试使用以下sed程序(适用于只包含1个类名的行)

sed -r '/ACME/{h;s/ACME_.*$//1;x;s/^.*(ACME.*)$/\\\1/;s/_/\\/g;x;G;s/\n//1}'

但它实际上只做

sed -r '/ACME/s/_/\\/g'

我更喜欢使用sed或awk的解决方案(仅为了提高我的cli技能),但任何其他解决方案都可以。

4 个答案:

答案 0 :(得分:1)

空格以及大多数特殊字符(但最重要的是,不是_)会结束一个单词,因此我认为单词边界应该很好地识别类名。所以,使用GNU sed:

sed 's/\>/\n/g; :a s/\<\(ACME[^\n]*\)_\([^\n]*\)/\1\\\2/; ta; s/\<ACME/\\&/g; s/\n//g' filename

其工作原理如下:

s/\>/\n/g

在关闭单词边界后放置换行符。我们稍后使用它来匹配(有点)非贪婪。完成此步骤后,您的行将变为

$locale_test
 = (new
 ACME_Common_Factory
())->createLocale
(ACME_Common_Enum_Civility
::MR
);

这使我们能够轻松识别ACME名称空间中的名称:\<ACME[^\n]*,并在ACME名称空间中标识包含下划线的名称:\<ACME[^\n]*_[^\n]*。我们可以使用它来查找ACME名称中的下划线并逐个替换它们:

:a                                      # jump label for looping
s/\<\(ACME[^\n]*\)_\([^\n]*\)/\1\\\2/   # Attempt replacement
ta                                      # if it happened, go back to a.

之后,它只是

s/\<ACME/\\&/g

\放在前面,然后

s/\n//g

删除我们放在那里的换行标记。

请注意,我怀疑在Perl中这会更容易。

答案 1 :(得分:1)

这可能适合你(GNU sed):

sed -r ':a;s/(ACME[a-zA-Z\\]*)_/\1\\/;ta;s/ACME/\\&/g' file

答案 2 :(得分:0)

这个怎么样?

sed -r -e '/ACME_[^\(:]*/s/_/\\/g' -e 's/(ACME\\)/\\\1/g'

答案 3 :(得分:0)

我终于找到了@Wintermute启发的答案

sed -r ':a s/(ACME[^;:\(]*)_([^;:\(]+)/\1\\\2/g; ta' file