用 sed 替换模式中的字符

Replace a char within a pattern with 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 个 class 名称的行)

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

但它实际上只做了一点

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

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

这个呢?

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

空格和大多数特殊字符(但重要的是,不是 _)结束一个单词,所以我相信单词边界应该很好地用于识别 class 名称。所以,使用 GNU sed:

sed 's/\>/\n/g; :a s/\<\(ACME[^\n]*\)_\([^\n]*\)/\/; 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]*\)/\/   # Attempt replacement
ta                                      # if it happened, go back to a.

之后就是

s/\<ACME/\&/g

\放在前面,

s/\n//g

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

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

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

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

这可能适合您 (GNU sed):

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