Bash:検索で与えられたパターンの最後の項目を置き換えて置き換える

Bash:検索で与えられたパターンの最後の項目を置き換えて置き換える

これバッシュハッカーウィキ説明する

${PARAMETER/PATTERN/STRING}

${PARAMETER//PATTERN/STRING}

This one can substitute (replace) a substring matched by a
pattern, on expansion time. The matched substring will be entirely
removed and the given string will be inserted.

The first one (one slash) is to only substitute the first
occurrence of the given pattern, the second one (two slashes) is
to substitute all occurrences of the pattern.

array[@]このアプローチは構文を使用してBash配列でも機能します。しかし、誰かが特定のパターンの最後の発生を置き換えたいとしましょう。 Bashは明らかにこれを行う方法を提供していません。

これは、単一の文字列と通常の文字列であるパターンに対して行うことができます。https://unix.stackexchange.com/a/187920/4671)

s=/foo/bar/baz
echo ${s%/*}/prefix-${s##*/}

これは作る

/foo/bar/prefix-baz

しかし、これは配列では機能しません。しかし、次のように配列に対して明示的なループを作成することは可能です。

a=(foo/bar/baz foo/bar/boo)
b=()
for i in "${a[@]}"; do
    b+=("${i%/*}/prefix-${i##*/}")
done
echo "${b[@]}"

これは作る

foo/bar/prefix-baz foo/bar/prefix-boo

だから、2つの関連する質問があります。

  1. Bashが最後の一致を置き換えるオプションを提供しないのはなぜですか?これは実装されていない機能ですか?それとも実装できない技術的な理由がありますか?これは奇妙な空白のように見えるからです。他のシェルとの比較を歓迎します。

  2. 配列を繰り返さずに最後の一致を置き換える方法はありますか?明らかにZshは専門家が使用するものなので、必要に応じてZshソリューションを自由に提供してください。

ベストアンサー1

私はそれが存在すると確信していますが、その機能を持つどの言語の演算子もわかりません。sedsを見るとn番目の項目をにs/../../置き換えることができますが、最後の項目から始まる項目の数は変更できません。s/../../n

私はそれが機能をあまりにもあいまいにするようだと思います。

kshここで「」と「逆参照」を使用できます${var/pattern/replacement}

そしてzsh

set -o extendedglob
b=("${a[@]/%(#m)[^\/]#/prefix-$MATCH}")

(#m)ペアの一致する部分キャプチャが有効になっている場合$MATCH

または:

b=("${(S)a[@]/%(#b)\/(*)//prefix-$match[1]}")

(#b)逆参照を有効にして、グループの一致部分を配列の(...)要素としてキャプチャし、一致をあまり欲張りません$match)。S

そしてksh93

b=("${a[@]/%*([^\/])/prefix-\1}")

では、zsh次のこともできます。

dirs=($a:h)
new_bases=(prefix-$^a:t)
b=()
printf -v b %s/%s ${dirs:^new_bases}

おすすめ記事