Bashで文字列の最後のx文字にアクセスする


124

${string:0:3}文字列の最初の3文字にアクセスできることがわかりました。最後の3文字にアクセスする同等の簡単な方法はありますか?

回答:


235

の最後の3文字string

${string: -3}

または

${string:(-3)}

(最初のフォーム:との間のスペースに注意してください-3)。

リファレンスマニュアルのシェルパラメータ拡張を参照してください:

${parameter:offset}
${parameter:offset:length}

Expands to up to length characters of parameter starting at the character
specified by offset. If length is omitted, expands to the substring of parameter
starting at the character specified by offset. length and offset are arithmetic
expressions (see Shell Arithmetic). This is referred to as Substring Expansion.

If offset evaluates to a number less than zero, the value is used as an offset
from the end of the value of parameter. If length evaluates to a number less than
zero, and parameter is not ‘@’ and not an indexed or associative array, it is
interpreted as an offset from the end of the value of parameter rather than a
number of characters, and the expansion is the characters between the two
offsets. If parameter is ‘@’, the result is length positional parameters
beginning at offset. If parameter is an indexed array name subscripted by ‘@’ or
‘*’, the result is the length members of the array beginning with
${parameter[offset]}. A negative offset is taken relative to one greater than the
maximum index of the specified array. Substring expansion applied to an
associative array produces undefined results.

Note that a negative offset must be separated from the colon by at least one
space to avoid being confused with the ‘:-’ expansion. Substring indexing is
zero-based unless the positional parameters are used, in which case the indexing
starts at 1 by default. If offset is 0, and the positional parameters are used,
$@ is prefixed to the list.

この答えはいくつかの通常の見解を得るので、John Rixのコメントに対処する可能性を追加しましょう。彼が言及しているように、文字列の長さが3未満の場合${string: -3}、空の文字列に展開されます。この場合、の展開がstring必要な場合は、以下を使用できます。

${string:${#string}<3?0:-3}

これはShell Arithmetic?:で使用される可能性のある三項if演算子を使用します。文書化されているように、オフセットは算術式であるため、これは有効です。


5
文字列が指定した負のオフセットより短い場合、これは機能しないことに注意してください。そのような場合、空の文字列を取得するだけです。
John Rix

2
@gniourf_gniourfコマンド置換と一緒にこれをどのように使用できますか?ホスト名の最後の3文字を抽出しようとしています deppfx@localhost:/tmp$ echo ${$(hostname): -3} -bash: ${$(hostname): -3}: bad substitution
deppfx

3
@deppfx:Bashではできません。一時変数を使用しますtemp=$(hostname); echo "${temp: -3}"。bashにもHOSTNAME変数があります(これはの出力と異なる場合と異なる場合がありますhostname)。使用したい場合は、実行してくださいecho "${HOSTNAME: -3}"
gniourf_gniourf 2015年

パイプの出力からこれをどのように使用できますか?例えば、some func | echo ${string: -3}-どのように私はの出力に割り当てるかsome funcををstring
マイケルヘイズ

1
@MichaelHaysは:ちょうどあなたの関数の出力を割り当てstring=$(some func)、その後とecho "${string: -3}"
gniourf_gniourf

48

使用できますtail

$ foo="1234567890"
$ echo -n $foo | tail -c 3
890

最後の3文字を取得するためのやや遠回りの方法は次のようになります。

echo $foo | rev | cut -c1-3 | rev

2
「テイル」は、ダッシュで、bashが使用できない場合にも役立ちます。たとえば、upstartスクリプトセクション。
vskubriev 2017年

13

別の回避策はgrep -o、小さな正規表現のマジックを使用して、3つの文字を取得し、その後に行末を取得することです。

$ foo=1234567890
$ echo $foo | grep -o ...$
890

オプションで最後の1〜3文字を取得するには、3文字未満の文字列の場合、次のegrep正規表現を使用できます。

$ echo a | egrep -o '.{1,3}$'
a
$ echo ab | egrep -o '.{1,3}$'
ab
$ echo abc | egrep -o '.{1,3}$'
abc
$ echo abcd | egrep -o '.{1,3}$'
bcd

5,10最後の5〜10文字を取得するなど、さまざまな範囲を使用することもできます。


7

質問とgniourf_gniourfの回答を一般化するために(これは私が探していたものです)、たとえば、文字の範囲を最後から7番目から最後から3番目までカットしたい場合は、次の構文を使用できます。

${string: -7:4}

ここで、4はコースの長さです(7-3)。

さらに、gniourf_gniourfのソリューションは明らかに最良で最も近いものですが、単にcutを使用して別のソリューションを追加したかっただけです。

echo $string | cut -c $((${#string}-2))-$((${#string}))

これは、長さ$ {#string}を個別の変数として定義することにより、2行で行うと読みやすくなります。


他の回答で言及されていない変形はcut、最初に開始/停止を計算し、次にこれらの変数をパラメーター展開で使用するというこのアプローチを組み合わせることです(またcut、bashオフセットがそれぞれ1と0で始まることに言及する価値があるため、これは必要になります)私はここではしていませんが、計算に含まれます):start=$((${#string}-3)); stop=$((${#string}));次に、echo ${string: $start : $stop}vsecho $string | cut -c "$start"-"$stop"
マイケル2018

(ああ、気にしないでください-私のコメントでは、文字列が短すぎるという問題に対処しておらず、出力もまったく発生していません-カットと文字列のパラメータ展開の両方です。それでも、変数に分割します(必ずしも追加のコマンドを呼び出す必要はありません)読みやすくし、それでも良い考えだと思います。)
michael
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.