web-dev-qa-db-ja.com

sedを使用して最後に出現する文字を置き換える

複数行の文字列変数内で最後に出現する文字を置き換えようとしています。

最後の|`に置き換える必要があります。

1
Chris Pavey

revをパイプでつなぎ、最初のオカレンスを置き換えてから、もう一度revを介してパイプすることができます。

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

または、純粋なsedで、||を含まないものが続く`に置き換え、その後に同じシーケンスを続ける必要があります。

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

それらの最初のものは読みやすく、理解しやすいと私は主張します。

1
Toby Speight

.*が貪欲であるという事実を利用できます。

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

または使用:

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

Tobyがすでに示しているように、|に続いて、|を含まないものを行末まで一致させるには、このアプローチは1文字の置換に対してのみ機能します。

複数行の文字列シェル変数でGNU sedに置き換えるには、入力を改行区切りではなくNUL区切りとして扱う-zオプションを使用できます。

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]}
2
$ printf '%s\n' "$str"
abc|def
ghi|jkl
$ printf '%s\n' "${str%\|*}"'`'"${str##*\|}"
abc|def
ghi`jkl
  • ${str%\|*}は、最後の|とそれが削除された後のすべての文字列に展開されます。
  • ${str##*\|}は、最後の|とそれが削除される前のすべての文字列に展開されます。

上記の2つのパラメーター置換を組み合わせて、`を間にすると、結果の文字列が得られます。

0
Kusalananda