私のbash
スクリプトには、文字列とそのプレフィックス/サフィックスがあります。元の文字列からプレフィックス/サフィックスを削除する必要があります。
たとえば、次の値があるとします。
string="hello-world"
prefix="hell"
suffix="ld"
次の結果を取得するにはどうすればよいですか?
result="o-wor"
私のbash
スクリプトには、文字列とそのプレフィックス/サフィックスがあります。元の文字列からプレフィックス/サフィックスを削除する必要があります。
たとえば、次の値があるとします。
string="hello-world"
prefix="hell"
suffix="ld"
次の結果を取得するにはどうすればよいですか?
result="o-wor"
回答:
$ foo=${string#"$prefix"}
$ foo=${foo%"$suffix"}
$ echo "${foo}"
o-wor
${${string#prefix}%suffix}
がうまくいきません。
sedの使用:
$ echo "$string" | sed -e "s/^$prefix//" -e "s/$suffix$//"
o-wor
sedコマンド内では、^
文字はで始まるテキストに一致$prefix
し、末尾はで$
終わるテキストに一致します$suffix
。
AdrianFrühwirthは、以下のコメントでいくつかの良い点を述べていますがsed
、この目的のために非常に役立ちます。$ prefixと$ suffixの内容がsedによって解釈されるという事実は、良い場合も悪い場合もあります。注意を払っている限り、問題はありません。美しさは、次のようなことができることです。
$ prefix='^.*ll'
$ suffix='ld$'
$ echo "$string" | sed -e "s/^$prefix//" -e "s/$suffix$//"
o-wor
これはあなたが望むものかもしれません、そしてbash変数置換よりもより洗練されていてより強力です。スパイダーマンが言うように、大きな力には大きな責任が伴うことを覚えているなら、大丈夫です。
sedの簡単な紹介は、http://evc-cit.info/cit052/sed_tutorial.htmlにあります。
シェルとその文字列の使用に関する注意:
与えられた特定の例では、以下も同様に機能します:
$ echo $string | sed -e s/^$prefix// -e s/$suffix$//
...しかし理由は次のとおりです:
文字列にスペースが含まれている場合でも、単一の引数としてコマンドに表示されるため、コマンドラインで文字列を引用符で囲むことは、一般的には良い習慣です。同じ理由で$ prefixと$ suffixを引用しています:sedへの各編集コマンドは1つの文字列として渡されます。変数の補間が可能なため、二重引用符を使用しています。単一引用符を使用した場合、sedコマンドはリテラル$prefix
を取得することになり、$suffix
これは確かに私たちが望んでいたものではありません。
また、変数prefix
とを設定するときに一重引用符を使用していることに注意してくださいsuffix
。文字列の何も解釈されないようにしたいので、それらを単一引用符で囲み、補間は行われません。繰り返しになりますが、この例では必要ないかもしれませんが、始めるのはとても良い習慣です。
$string
単語分割とグロブの影響を受けます。2)$prefix
そして、解釈する$suffix
表現を含めることができますsed
。たとえば、正規表現や、コマンド全体を壊す区切り文字として使用される文字。3)sed
2回の呼び出しは必要ありません(-e 's///' -e '///'
代わりに行うことができます)。パイプも回避できます。たとえば、考えるstring='./ *'
および/またはprefix='./'
、それが原因に恐ろしく破る見る1)
と2)
。
/
、を使用できなかったためsed "s#^$prefix##
、代わりにを使用しました。(脆弱性:ファイル名にを含めることはできません#
。私がファイルを制御しているので、安全です。)
#
、sedの区切り文字として使用する選択の制限は、その文字を含むファイルを処理できないことを意味すると言っていました。
接頭辞と接尾辞の長さを知っていますか?あなたの場合:
result=$(echo $string | cut -c5- | rev | cut -c3- | rev)
またはより一般的な:
result=$(echo $string | cut -c$((${#prefix}+1))- | rev | cut -c$((${#suffix}+1))- | rev)
しかし、AdrianFrühwirthの解決策は非常に優れています。知らなかった!
パスからプレフィックスを削除するためにgrepを使用します(これはによって適切に処理されませんsed
)。
echo "$input" | grep -oP "^$prefix\K.*"
\K
その前のすべての文字を一致から削除します。
grep -P
非標準の拡張です。お使いのプラットフォームでサポートされていれば、より強力になりますが、コードを適切に移植できるようにする必要がある場合、これは疑わしいアドバイスです。
grep
。以前のバージョンには実際には-P
BSDからのオプションgrep
がありましたが、削除されました。
$ string="hello-world"
$ prefix="hell"
$ suffix="ld"
$ #remove "hell" from "hello-world" if "hell" is found at the beginning.
$ prefix_removed_string=${string/#$prefix}
$ #remove "ld" from "o-world" if "ld" is found at the end.
$ suffix_removed_String=${prefix_removed_string/%$suffix}
$ echo $suffix_removed_String
o-wor
#$ prefix:追加#は、部分文字列「hell」が最初に見つかった場合にのみ削除されるようにします。%$ suffix:%を追加すると、部分文字列 "ld"が最後に見つかった場合にのみ削除されるようになります。
これらがなければ、部分文字列「hell」と「ld」は、途中で見つかったとしても、どこでも削除されます。
/
、文字列の直後にもスラッシュがありますが、それは何のためですか?
私は正規表現でキャプチャグループを利用します。
$ string="hello-world"
$ prefix="hell"
$ suffix="ld"
$ set +H # Disables history substitution, can be omitted in scripts.
$ perl -pe "s/${prefix}((?:(?!(${suffix})).)*)${suffix}/\1/" <<< $string
o-wor
$ string1=$string$string
$ perl -pe "s/${prefix}((?:(?!(${suffix})).)*)${suffix}/\1/g" <<< $string1
o-woro-wor
((?:(?!(${suffix})).)*)
のコンテンツが${suffix}
キャプチャグループから除外されることを確認します。例としては、と同等の文字列です[^A-Z]*
。そうでなければあなたは得るでしょう:
$ perl -pe "s/${prefix}(.*)${suffix}/\1/g" <<< $string1
o-worldhello-wor