逆参照を使用しても、複数のパターンの変数のテキストを同時に置き換える方法はありますか?
たとえば、FILE=filename.ext
に変更したいのですがfilename_sometext.ext
、ファイル拡張子が何であるかわかりません.ext
。私が知っているのは、拡張子が最後の点の後ろにあるということだけです。したがって、2つのステップで行うことができます。
EXT=${FILE##*.}
FILE=${FILE%.*}_sometext.$EXT
1つのステップで完了できますか(例:${FILE/.\(*\)/_sometext.\1}
[これは機能しません])?
sed
しかし、/などのない純粋なawk
シェルでこれを行う必要があります。私のシェルはですがksh
、bashismsでこれを行う方法があればそれも知りたいです。
答え1
Bash パラメータ拡張表現変数(FILE
例では)はパラメータ名でなければなりません。だから彼らは巣を作らない。最後の部分は${param/pattern/replacement}
文字列でなければなりません。したがって、逆参照はサポートされていません。
私の唯一の提案は、以下を使用することです。
${EXT:+.$EXT}
ファイルに拡張子がない場合に後ろにドットを追加したくない場合。
修正する
明らかに逆参照がサポートされていますクッシュ 93。
だからあなたは次のようなものを使うことができます
FILE="${FILE/@(.*)/_something\1}"
答え2
FILE=${FILE%.*}_sometext.${FILE##*.}
この特別なケースでは、それがそれを行うと思います。
答え3
変わりやすい。
すべてのシェルで変数または値を連結できます。
$ a=One; b=Two; c=Three
$ d="$a$b$c"; echo $d
OneTwoThree
この${parameter%word}
構造POSIXですほとんどのシェルは長い間この機能をサポートしてきました。
前提として、FILE=filename.ext
次のようにすることができます。
$ FILE="${FILE%.*}_sometext.${FILE##*.}"; echo "$FILE"
filename_sometext.ext
これは(要求どおり)1行で、ほとんどのシェルで機能します。
変数を使用することも可能です(複数の点がある場合でも)。
#!/bin/bash
FILE=file.one.name.ext
ADDTEXT="_sometext"
EXT="${FILE##*.}"
echo "EXT=$EXT"
echo "final FILE=${FILE%.*}${ADDTEXT}.$EXT"
または、次の1行だけを使用してください。
ONEFILE=${FILE%.*}${ADDTEXT}.${FILE##*.}
echo "one FILE=$ONEFILE"
パターン交換
トリッキーな部分は、${parameter/pattern/string}
「パターン置換」を使用しようとすることです。
変数は多くのシェルで動作します(ビジボックスの再作成も含む)。
NEWTEXT="${ADDTEXT}.${FILE##*.}"
echo "ash FILE=${FILE/.*/${NEWTEXT}}"
しかし、古いsh
Elsではそうではありません。
以下でのみ機能しますFILE=filename.ext
:
bash(およびksh、ksh93、mksh、zsh)では機能しますが、ash、dash、sh、またはcshでは機能しません。
echo "bash FILE=${FILE/%.*/${ADDTEXT}.${FILE##*.}}"
%
引数の終わりに一致を表示するために文字を使用することに注意してください(ただし、残念ながら貪欲なので、すべてのポイントを食べてしまいますFILE=file.one.name.ext
)。
結論として
置換がどれほど貪欲であるかを制御する最も良い方法は、別の変数を使用することです(「パターン置換」のいくつかの変数の代わりに)。
答え4
FILE="${FILE%.*}_sometext${FILE#"${FILE%.*}"}"
シェル変数に$FILE
a が含まれている場合、上記のコマンドは前の.
値から最後の値以降の.
すべての値を引いた値を再割り当てします。_sometext
そして、最後の前の値.
とそれ以降のすべての値を維持します。
だから:
FILE=some.dot
FILE="${FILE%.*}_sometext${FILE#"${FILE%.*}"}"
printf %s\\n "$FILE"
some_sometext.dot
シェル変数が$FILE
次の場合いいえ点が含まれている場合_sometext
文字列は前の値の終わりにのみ追加されます。
FILE=no_dots_at_all
FILE="${FILE%.*}_sometext${FILE#"${FILE%.*}"}"
printf %s\\n "$FILE"
no_dots_at_all_sometext
これは、私が行ったようにパラメータ拡張を入れ子にしない場合に発生する可能性のある動作との重要な違いです。
FILE=no_dots_at_all
FILE="${FILE%.*}_sometext${FILE##*.}"
printf %s\\n "$FILE"
no_dots_at_all_sometextno_dots_at_all
パラメータ拡張をネストすると内部から外部に評価されるため、最初に発生することは次のとおりです。
for FILE in some.dot no_dots_at_all
do printf %s\\n '${FILE#'"${FILE%.*}"'}'
done
${FILE#some}
${FILE#no_dots_at_all}
...シェルは一致するすべてのビットを削除し、残りを外部拡張から削除されたパターンとして使用します。だから、いいえ一致するビットと変数は完全に拡張され、外部拡張は削除されます。みんな変数の値を式に2回置き換える代わりに使用します。