Ответ 1
bash> name=joshua
bash> echo $name | sed 's/\([oa]\)/X\1/g'
jXoshuXa
Как включить регулярное выражение в замещающее выражение в BASH?
Нерабочий пример:
#!/bin/bash
name=joshua
echo ${name//[oa]/X\1}
Я ожидаю вывод jXoshuXa
с заменой \1
на соответствующий символ.
На самом деле это не работает и выводит jX1shuX1
.
bash> name=joshua
bash> echo $name | sed 's/\([oa]\)/X\1/g'
jXoshuXa
Возможно, не такой интуитивно понятный, как sed
и, возможно, довольно неясный, но в духе полноты, в то время как BASH, вероятно, никогда не будет поддерживать переменные захвата вместо (по крайней мере, не в обычном порядке, поскольку круглые скобки используются для расширенного сопоставления с образцом), но это все еще возможно захватить шаблон при тестировании с помощью бинарного оператора =~
чтобы получить массив совпадений с именем BASH_REMATCH
.
Возможен следующий пример:
#!/bin/bash
name='joshua'
[[ $name =~ ([ao].*)([oa]) ]] && \
echo ${name/$BASH_REMATCH/X${BASH_REMATCH[1]}X${BASH_REMATCH[2]}}
Условное совпадение регулярного выражения ([ao].*)([oa])
фиксирует следующие значения в $BASH_REMATCH
:
$ echo ${BASH_REMATCH[*]}
oshua oshu a
Если найдено, мы используем расширение ${parameter/pattern/string}
чтобы найти шаблон oshua
в параметре со значением joshua
и заменить его комбинированной строкой Xoshu
и Xa
. Однако это работает только для нашего примера строки, потому что мы знаем, чего ожидать.
Для чего - то, что функции больше похожи на матч всех или глобальных регулярных выражений коллегами следующий пример жадный матч для любого неизмененном o
или a
вставления X
от задней стенки к передней.
#/bin/bash
name='joshua'
while [[ $name =~ .*[^X]([oa]) ]]; do
name=${name/$BASH_REMATCH/${BASH_REMATCH:0:-1}X${BASH_REMATCH[1]}}
done
echo $name
Первая итерация изменяет $name
на joshuXa
и, наконец, на jXoshuXa
прежде чем условие не jXoshuXa
и цикл завершится. Этот пример работает аналогично виду выражения /(?<!X)([oa])/X\1/
котором предполагается, что нужно заботиться только о символах o
или a
префикса X
Выход для обоих примеров:
jXoshuXa
NJoy!
Подстановка строки вопроса bash: подвыражения, совпадающие со ссылкой, были помечены как дубликаты этого, несмотря на требование, что
Код выполняется в длинном цикле, он должен быть однострочным и не запускать подпроцессы.
Итак, ответ:
Если вы действительно не можете позволить запустить sed в подпроцессе, не используйте bash! Вместо этого используйте perl, цикл чтения-обновления-вывода будет в несколько раз быстрее, а разница в синтаксисе невелика. (Ну, вы не должны забывать точку с запятой.)
Я переключился на Perl, и был только один вопрос: поддержка Unicode не была доступна на одном из компьютеров, мне пришлось переустанавливать пакеты.