Bashの文字列から最後のn文字を削除する方法は?


回答:


15

最初に、あなたはあなたが何をしたいかについて明確であるべきです。文字列がで終わり、.rtfを削除したい.rtf場合は、を使用できますvar2=${var%.rtf}。サフィックスがわからないが、最後からすべて削除したい.場合は、を使用できますvar2=${var%.*}。最初のものまですべてを維持したい.場合は、var2=${var%%.*}。最後の2つのオプションは、期間が1つしかない場合は同じ結果になりますが、期間が複数ある場合は、どちらを使用するかを決める必要があります。

常に正確な数の文字を常に削除したい場合は、いくつかのオプションがあります。

具体的にはbashを指定したので、bashビルトインから始めます。最も長く機能したのは、上記で使用した接尾辞削除構文と同じです。4文字を削除するには、次を使用します。var2=${var%????}。文字ごとに1つの疑問符を削除する必要があるため、部分文字列の長さが長くなると扱いにくくなります。

少し新しいのは、部分文字列の抽出ですvar2=${var::${#var}-4}。ここで、の代わりに任意の数を入力4して、異なる数の文字を削除できます。(${#var}は文字列の長さに置き換えられるため、これは実際には最初の(長さ-4)文字を保持するように求めています。)

新しいバージョンのbash(具体的には4+、つまりMacOSに同梱されているバージョンが機能しないことを意味します)では、これをに単純化できますvar2=${var::-4}

実際にbashを使用していないが、他のPOSIXタイプのシェルを使用している場合、サフィックスの削除は、通常の古いダッシュ(他のどれも使用できない)でも機能します。zshではすべて機能しますが0、コロンの間にaを置くvar2=${var:0:-4}必要があります。など。kshでは、0が必要で、明示的な長さ4の式を使用する必要もあります。var2=${var:0:${#var}-4}

もちろん、ユーティリティプログラムを使用してコマンド置換を行うこともできます。うまくいくものはたくさんありますが、のようなものvar2=$(cut -c -4 <<<"$var")がおそらく最も短いオプションです。


241

あなたはこのようにすることができます:

#!/bin/bash

v="some string.rtf"

v2=${v::-4}

echo "$v --> $v2"

9
bash 4+だと思います。
Etan Reisner、2014

69
それはbash4+ですが、以前のバージョンでは少し長く使用できます${v::${#v}-4}
chepner 2014

8
私のために働いていませんでした、bashは ''悪い代用 ''
Ivan Marjanovic

15
何らかの理由で、zsh ${v::-4}croaksで「zsh:閉じ中かっこが必要です」。しかし、以下の@fredtantiniの答えはうまくいき${v:0:-4}ます。
Pierre D

6
エラー:-2:サブストリング式<0
Edward

173

文字列の末尾から4文字を削除するには、を使用します${var%????}

最終.使用後にすべてを削除するには${var%.*}


12
純粋なシェルの答えであり、ライセンスの問題によりBASH 4.xの実装を拒否した多くのシステムで見られるBASH 3.xで動作します。
David W.

1
これは、短い文字列を取得することに対して堅牢であるためクールです。その場合、インデックスオフセットバリアントは失敗します。
ラファエル

bash 3.2.25で動作します-最良の答え-私が探していたもの
capser

すばらしい答えです。ひもの前の取り外しはどうですか?
user2023370

3
@ user2023370ドキュメントを参照すると、それに対応するパラメータ置換があることがわかります${var#????}
Tripleee

48

私のために働いたのは:

echo "hello world" | rev | cut -c5- | rev
# hello w

しかし、ファイル内の行をトリミングするためにそれを使用したので、見苦しく見えます。実際の用途は次のとおりです。

cat somefile | rev | cut -c5- | rev

cut開始位置からトリミングするまでしか得られませんが、可変長の行が必要な場合は悪いことです。したがって、このソリューションrevは文字列を逆転()し、終了位置に関連付けてから、cut前述のように使用し、それをrev元の順序に(再び)逆転させます。


これは正しくなく、何が求められているかに対する答えでもありません。rev文字列ではなく行を反転します。echo $SOME_VAR | rev | ...おそらく期待どおりに動作しません。
Mohammad Nasirifar

2
@Mohammad 引用壊れているためこれ 1行です。
Tripleee

38

変数の展開/部分文字列の置換を使用:

$ {var /%Pattern / Replacement}

varのサフィックスがパターンに一致する場合、パターンを置換に置き換えます。

だからあなたはできる:

~$ echo ${var/%????/}
some string

または、

あなたがいつも同じ4文字を持っているなら

~$ echo ${var/.rtf/}
some string

常に末尾が.xyz次の場合:

~$ echo ${var%.*}
some string

文字列の長さを使用することもできます。

~$ len=${#var}
~$ echo ${var::len-4}
some string

または単に echo ${var::-4}


len=${#var}; echo ${var::len-4}短縮できますecho ${var:0:-4}:-)編集:または@iyonizerが指摘したように、ただecho ${var::-4}...
anishsane

26

あなたはsedを使うことができました、

sed 's/.\{4\}$//' <<< "$var"

例:

$ var="some string.rtf"
$ var1=$(sed 's/.\{4\}$//' <<< "$var")
$ echo $var1
some string

1
そしてどのように結果を割り当てるのvar2ですか?
becko 14

このように1行で機能するため、これは良いです... | sed 's /。\ {4 \} $ //'。変数を使用せずに使用できる
Sam

3

私は次のことを試しましたが、うまくいきました:

#! /bin/bash

var="hello.c"
length=${#var}
endindex=$(expr $length - 4)
echo ${var:0:$endindex}

出力: hel


1

以下の例が役立つことを願って、

echo ${name:0:$((${#name}-10))} -> ${name:start:len}

  • 上記のコマンドでは、nameは変数です。
  • start 文字列の開始点です
  • len 削除する必要がある文字列の長さです。

例:

    read -p "Enter:" name
    echo ${name:0:$((${#name}-10))}

出力:

    Enter:Siddharth Murugan
    Siddhar

注:Bash 4.2は負の部分文字列のサポートを追加しました


これは、Etan Reisnerの回答のようなBourne互換の単純なパターン置換よりもはるかに冗長です。
Tripleee

0

これは文字列のサイズを計算することによって私のために働きました。
返す必要がある値をエコーし​​て、以下のように保存するのは簡単です

removechars(){
        var="some string.rtf"
        size=${#var}
        echo ${var:0:size-4}  
    }
    removechars
    var2=$?

いくつかの文字列


0

この場合、削除するファイルに同じサフィックスがあると想定して、basenameを使用できます。

例:

basename -s .rtf "some string.rtf"

これは「何らかの文字列」を返します

サフィックスがわからず、最後のドット以降のすべてを削除する場合:

f=file.whateverthisis
basename "${f%.*}"

「ファイル」を出力

%はチョップを意味します。切り刻んでいるもの、*はワイルドカード

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.