用 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
我正在尝试更改以使用 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