web-dev-qa-db-ja.com

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

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

97
aldorado

stringの最後の3文字:

${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}

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

184
gniourf_gniourf

tailを使用できます。

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

最後の3文字を取得するためのやや迂回的な方法は、次のように言うことです。

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

別の回避策は、grep -oを少し正規表現の魔法で使用して、3文字の後に行末を取得することです。

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

オプションで、3文字未満の文字列の場合、最後の1〜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文字を取得することもできます。

8
Aurelio Jargas

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

${string: -7:4}

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

さらに、gniourf_gniourfの解決策は明らかに最適で最も適切ですが、cutを使用して別の解決策を追加したかっただけです。

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

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

4
Adrian Tompkins