Заменить символ в шаблоне с помощью sed

Я пытаюсь изменить, чтобы перенести мой php-код с использованием соглашения ZF1 / PEAR в пространства имен.

Итак, я хочу изменить

$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 (просто для улучшения моих навыков), но подойдет любое другое решение.

2

Решение

Пробелы, а также большинство специальных символов (но, главное, не _) завершение слова, поэтому я считаю, что границы слов должны служить для идентификации имен классов. Итак, используя 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

Другие решения

Это может работать для вас (GNU sed):

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

Как насчет этого ?

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

Я наконец нашел ответ, вдохновленный @Wintermute

sed -r ':a s/(ACME[^;:\(]*)_([^;:\(]+)/\1\\\2/g; ta' file
0
По вопросам рекламы [email protected]