1. ホーム
  2. バッシュ

[解決済み】Bashで文字列から最後のn文字を削除する方法は?

2022-03-26 04:01:30

質問

私は、変数 var のような文字列を保持するBashスクリプトの中にあります。

echo $var
"some string.rtf"

この文字列の最後の4文字を削除して、その結果を新しい変数に代入したい。 var2 というように

echo $var2
"some string"

どうすればいいのでしょうか?

どのように解決するのですか?

まず、通常は意図を明示したほうがよいでしょう。つまり、文字列の末尾が .rtf を削除したい場合、その .rtf を使えばいいのです。 var2=${var%.rtf} . この方法の有用な点の1つは、もし文字列 がない場合 で終わる。 .rtf の場合、全く変更されません。 var2 の変更されていないコピーが含まれます。 var .

ファイル名のサフィックスを削除したいが、それが何であるかを正確に知らない、あるいは気にしない場合は、次のようにします。 var2=${var%.*} で始まるものをすべて削除するには、最後の . . を含まないものだけを残しておきたい場合は、以下のようになります。 最初 . を使用することができます。 var2=${var%%.*} . これらのオプションは、1つの . しかし、複数ある場合は、文字列のどの端から作業するかを選択することになります。一方、もし . という文字列があります。 var2 は、またしても変更されない var .

もし、本当に特定の 番号 という文字が含まれている場合、以下のような選択肢があります。

あなたはこのようなタグを付けました。 bash ということで、まずはbashのビルトインから。一番長く使えているのは、上で使ったのと同じサフィックス除去の構文で、4文字を除去するには var2=${var%????} . または、4文字のうち最初の1文字がドットの場合のみ削除する場合は var2=${var%.???} のようなものです。 var2=${var%.*} が、ドット以降の部分がちょうど3文字である場合にのみサフィックスを削除する。この方法で文字を数えるには、未知の文字を1つ削除するごとにクエスチョンマークが1つ必要になるので、部分文字列の長さが大きくなるとこの方法は扱いづらくなります。

新しいバージョンのシェルでは、部分文字列抽出というオプションがあります。 var2=${var:0:${#var}-4} . の代わりに任意の数字を入れることができます。 4 を使えば、異なる文字数を削除することができます。このとき ${#var} は文字列の長さに置き換えられるので、これは実際には最初の文字(インデックス0)から始まる(長さ-4)文字を抽出して保持するように要求していることになります。この方法では、文字列がパターンにマッチする場合にのみ変更を加えるというオプションがなくなります。文字列の実際の値が何であろうと、コピーには最後の4文字以外が含まれることになります。

開始インデックスは省略可能で、デフォルトでは 0 になっています。 var2=${var::${#var}-4} . 実際、新しいバージョンのbash(特に4以降、つまりMacOSに同梱されているものは動作しない)は、負の長さを、文字列の終わりから数えて停止する文字のインデックスとして認識します。そのため、これらのバージョンでは、文字列の長さを表す式を取り除くことができます。 var2=${var::-4} .

bashではなく、他のPOSIX系シェルを使っている場合、パターンベースのサフィックス除去で % インデックスベースの部分文字列抽出ができない、古いダッシュでもです。Ksh と zsh は部分文字列抽出をサポートしていますが、明示的な 0 の開始インデックスを必要とします; zsh は負の終了インデックスもサポートしていますが、ksh は length 式を必要とします。zshは 配列 1から始まるが、それにもかかわらず 文字列 0から始まる このbash互換の構文を使用する場合 . しかし、zsh ではスカラーパラメータを文字の配列のように扱うこともできます。この場合、部分文字列構文は 1 ベースのカウントを使用し、開始位置と (含む) 終了位置をカンマで区切った括弧内に配置します。 var2=$var[1,-5] .

シェルに組み込まれたパラメータ展開を使う代わりに、もちろん何らかのユーティリティ・プログラムを実行して文字列を修正し、その出力をコマンド置換で取り込むことができます。動作するコマンドはいくつかあり、そのひとつが var2=$(sed 's/.\{4\}$//' <<<"$var") .