シェルで文字列の最後の文字を取得する方法は?


125

文字列の最後の文字を取得するために、次の行を記述しました。

str=$1
i=$((${#str}-1))
echo ${str:$i:1}

それはのために働きabcd/ます:

$ bash last_ch.sh abcd/
/

次の場合は機能しませんabcd*

$ bash last_ch.sh abcd*
array.sh assign.sh date.sh dict.sh full_path.sh last_ch.sh

現在のフォルダ内のファイルが一覧表示れます

回答:


95

これが、変数を引用する必要がある理由の1つです。

echo "${str:$i:1}"

それ以外の場合、bashは変数を展開し、この場合は出力前にグロビングを実行します。スクリプトにパラメーターを引用することもお勧めです(一致するファイル名がある場合)。

sh lash_ch.sh 'abcde*'

bashリファレンスマニュアルの展開の順序も参照してください。変数はファイル名展開の前に展開されます。

-1負のインデックスは文字列の最後から数えるので、最後の文字を取得するにはインデックスとして使用するだけです。

echo "${str: -1}"

コロン(:)の後のスペースは必須です。

このアプローチはスペースなしでは機能しません。


62
ところで、負のインデックスは右から数えるので"${1: -1}"十分です。
チョロバ2013

7
コメントではなく、正式な解決策として返信してください。
BMW

参考までに、これを「ワンライナー」で行うこともできますecho "${str:$((${#str}-1)):1}"。これにより、返される末尾の文字も変えることができます。このbash v4.1.0(1)での作業
SaxDaddy

16
@チョロバの答え:いまいましいスペースに注意してください!これは常に私を"${1:-1}
つまずか

192

@perrealごとに、変数を引用することが重要ですが、コメントで手元の質問に対するより簡単なアプローチを見つける前に、この投稿を5回程度読んだので...

str='abcd/'
echo "${str: -1}"

出力: /

str='abcd*'
echo "${str: -1}"

出力: *

これに上記に参加したすべての人に感謝します。スレッド全体に+1を適切に追加しました!


25
注:内側のスペースに注意してください${std: -1}。スペースがないと機能しません。私はこれに遭遇し、それ${std:~0}も機能することを発見しました(スペースの有無にかかわらず)。これが文書化された動作であるかどうかはわかりませんが、私はそれを調べる必要はありません。
Bart

4
文書化されています。man bash
さんのコメント

3
共有してくれてありがとう。BASHのマンページを読むのはほとんど圧倒的ですが、私は何度かそこに行ったことがあります。私は彼らがシェルスクリプトについての大学のコースを作ることができると思います笑
quickshiftin 2014年

3
.sh取得した文字を変数に割り当てようとすると、このソリューションはスクリプトでは機能しません。例えばdeclare LAST=$(echo "${str: -1}") :これはから始まる構文エラーを示す厄介な赤いバーになります
krb686

3
エディタの構文チェックがそのスペースを好きではない場合${str:0-1}
ttt

36

私はこれが非常に古いスレッドであることを知っていますが、私にとってどれが最もきれいな答えであるかについて誰も言及しませんでした:

echo -n $str | tail -c 1

なお、-nエコーは、末尾の改行が含まれていないだけようです。


15
$ {str:-1}よりもクリーンであることに近づいていない
shrewmouse '22

8
bash-ismに依存しないため、よりクリーンなので、どのPosixシェルでも動作します。
ジョンアイケンベリー、

最も「ベーシスト」とは何ですか?"$ {str:-1}"そして...最もクリーンなものは何ですか?"$ {str:-1}" Bashが最高です!:-)
ロジャー

大きなファイルの最後の文字を印刷しようとしている人にとっては、これは私のために仕事をしました:cat user / folder / file.json | tail -c 1 1を印刷したい文字数に置き換えることができます。
ディエゴセラーノ

5

awkスクリプトを使用した別のソリューション:

最後の1文字:

echo $str | awk '{print substr($0,length,1)}'

最後の5文字:

echo $str | awk '{print substr($0,length-5,5)}'

1
OPが要求したものではありませんが、これはファイルで使用するために私が見つけた最良のソリューションです。他のほとんどのアプローチは、次のようにファイルをそこにキャットすることでは機能しません: cat file | awk '{print substr($0,length,1)}'ありがとう!
xmar

4

単線:

${str:${#str}-1:1}

今:

echo "${str:${#str}-1:1}"

1
なぜ2組の括弧を使うのですか?また、4.2以降では、quickshiftinの回答に示されているように、負のオフセットを使用できます:echo "${str: -1}"で十分です(:との間のスペースに注意してください-)。
gniourf_gniourf 2015

2組の括弧が算術演算に使用されています
Eduardo Cuomo

いいえ。マニュアルの関連する部分を参照しください。長さオフセットは算術式です(シェル演算を参照)。したがって、あなたはすでにシェル算術にあり、括弧はまったく必要ありません。その上、あなたが言ったことが真実なら、で算術展開をするほうがより論理的でしょう$((...))
gniourf_gniourf 2015

@gniourf_gniourf正解です!以前の質問を理解しました。回答が更新されました
Eduardo Cuomo

4

これまでのすべての回答は、質問の「シェル」という単語がBashに相当することを意味しています。

これは、標準のBourneシェルでこれを行う方法です。

printf $str | tail -c 1

1
echo -nuser5394399によって提案されているように、$str特殊なフォーマット文字が含まれている場合の問題を回避します。
コンラッドマイヤー

-nスイッチがbashismです。それはダッシュなどの標準のBourneシェルでは機能しません...それが私の答えのポイントでした。
2018年

1
それほどバシズムではありませんが、POSIXはそれが実装定義であると認識します(「最初のオペランドが-nの場合、またはいずれかのオペランドに<backslash>文字が含まれている場合、結果は実装定義です」)。代わりにあなたの答えはprintf "%s" "$str" | ...:-) で修正できます。
コンラッドマイヤー

4

試してください:

"${str:$((${#str}-1)):1}"

たとえば:

someone@mypc:~$ str="A random string*"; echo "$str"
A random string*
someone@mypc:~$ echo "${str:$((${#str}-1)):1}"
*
someone@mypc:~$ echo "${str:$((${#str}-2)):1}"
g

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