Использование SED для замены последнего возникновения характера

С помощью Bash , используя compgen и type builtins , при условии отсутствия символа новой строки в именах команд:

IFS=$'\n'; set -f; type -p -- $(compgen -c | grep 'latex$')

2
30.10.2018, 13:29
3 ответа
$ printf '%s\n' "$str"
abc|def
ghi|jkl
$ printf '%s\n' "${str%\|*}"'`'"${str##*\|}"
abc|def
ghi`jkl
  • ${str%\|*}заменяется на строку с последним |и всем после него удаленным.
  • ${str##*\|}заменяется на строку с последним |и всем, что было до него.

Комбинация вышеуказанных двух подстановок параметров с `в -между ними дает результирующую строку.

0
27.01.2020, 21:58

Вы можете использовать тот факт, что .*жадный:

sed 's/\(.*\)|/\1`/'

Или используйте:

sed 's/|\([^|]*\)$/`\1/'

Для сопоставления с |, за которым следует что-то, что не содержит |, до конца строки, как уже было показано Тоби, но этот подход работает только для замены отдельных символов.

Чтобы заменить его в многострочной строковой переменной оболочки, в GNU sedвы можете использовать параметр -z, который обрабатывает ввод как с разделителями NUL, а не с разделителями новой строки:

var=$(printf %s "$var" | sed -z '...')

Другим подходом может быть выполнение подстановки с использованием стандартных операторов раскрытия параметров:

case $var in
  (*'|'*) var=${var%'|'*}'`'${var##*'|'}
esac

Или с этими sedкомандами, переведенными в их эквивалент оболочки:

Вksh93:

var=${var/@(*)'|'/\1'`'}
var=${var/%'|'*([^'|'])/'`'\1}

Вbash(предполагается, что строка не содержит последовательностей байтов, не образующих допустимых символов в текущей локали):

re='(.*)\|(.*)'
[[ $var =~ $re ]] && var=${BASH_REMATCH[1]}'`'${BASH_REMATCH[2]}

Вzsh:

set -o extendedglob
var=${var/(#b)(*)'|'/$match[1]'`'}

var=${var/%(#b)'|'([^'|']#)/'`'$match[1]}
3
27.01.2020, 21:58

Вы можете передать через rev, заменить первое вхождение, а затем снова через rev:

rev | sed -e 's/|/`/' | rev

В качестве альтернативы, в чистом sedвы хотите заменить |, за которым следует что-либо, кроме |, на `, за которым следует та же последовательность:

sed -e 's/|\([^|]*\)$/`\1/'

Я бы сказал, что первый из них легче читать и понимать.

1
27.01.2020, 21:58

Теги

Похожие вопросы