Usando sed para substituir a última ocorrência de caractere

2

Estou tentando substituir a última ocorrência de um caractere em uma variável de cadeia de várias linhas.

Eu preciso substituir o último | por ' .

    
por Chris Pavey 30.10.2018 / 11:54

3 respostas

1

Você pode canalizar por rev , substituir a primeira ocorrência e, em seguida, rev novamente:

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

Como alternativa, em sed puro, você deseja substituir | seguido por qualquer coisa que não inclua | com ' seguido pela mesma sequência:

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

Eu diria que o primeiro deles é mais fácil de ler e entender.

    
por 30.10.2018 / 12:01
2

Você pode usar o fato de que .* é ganancioso:

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

Ou use:

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

Para corresponder a | seguido por algo que não contenha | até o fim da linha, como já mostrado por Toby, mas essa abordagem só funciona para substituições de caracteres únicos.

Para substituí-lo em uma variável de shell de sequência multilinha, com GNU sed , você pode usar a opção -z , que trata a entrada como delimitada por NUL em vez de delimitada por nova linha:

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

Outra abordagem seria fazer a substituição usando operadores de expansão de parâmetro padrão:

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

Ou com esses comandos sed traduzidos para o equivalente em shell:

Em ksh93 :

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

Em bash (assumindo que a string não contém sequências de bytes que não formam caracteres válidos no local atual):

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

Em zsh :

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

var=${var/%(#b)'|'([^'|']#)/'''$match[1]}
    
por 30.10.2018 / 12:08
0
$ printf '%s\n' "$str"
abc|def
ghi|jkl
$ printf '%s\n' "${str%\|*}"'''"${str##*\|}"
abc|def
ghi'jkl
  • ${str%\|*} se expande para a string com o último | e tudo depois da remoção.
  • ${str##*\|} expande para a string com o último | e tudo antes de ser removido.

A combinação das duas substituições de parâmetro acima, com um ' entre, fornece a string de resultado.

    
por 30.10.2018 / 14:11