如何获取 shell 中字符串的最后一个字符?

为了得到字符串的最后一个字符,我编写了以下代码行:

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

列出当前文件夹中的文件

244308 次浏览

这就是为什么你需要引用你的变量的原因之一:

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

否则,bash 将扩展变量,在本例中,bash 将在打印输出之前进行 globbing。最好在脚本中引用参数(如果您有匹配的文件名) :

sh lash_ch.sh 'abcde*'

也可以参见 Bash 参考手册.Variables 中的展开顺序。变量在文件名展开之前展开。

为了得到最后一个字符,你应该使用 -1作为索引,因为负的索引从字符串的末尾开始计数:

echo "${str: -1}"

冒号(:)后面的空格是必需的。

这种方法在没有空间的情况下是行不通的。

每@perreal,引用变量是很重要的,但是因为我在找到一个更简单的方法来解决评论中的问题之前,已经读了这篇文章五遍了..。

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

或者按照注释中指出的那样使用 ${str:0-1}

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

注意 : ${str: -1}中的额外空间是 有需要,否则如果 str为 null 或空,则 ${str:-1}将导致 1作为默认值。

${parameter:-word}
Use Default Values.  If parameter is unset or null, the
expansion of word is substituted.  Otherwise, the value of
parameter is substituted.

感谢所有参与上述活动的人,我在整个帖子中适当地添加了 + 1!

echo $str | cut -c $((${#str}))

是个好办法

另一种使用 awk 脚本的解决方案:

最后一个字符:

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

最后5个字符:

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

单行:

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

现在:

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

我知道这是一个非常古老的线索,但没有人提到哪一个对我来说是最干净的答案:

echo -n $str | tail -c 1

注意,使用 -n只是为了使 echo 在末尾不包含换行符。

试试:

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

到目前为止,每个答案都暗示问题中的“ shell”等同于 Bash。

下面是在标准 Bourne shell 中实现这一点的方法:

printf "%s" "$str" | tail -c 1
expr $str : '.*\(.\)'

或者

echo ${str: -1}

对于 < a href = “ https://pubs.opengroup.org/onlinepubs/9699919799/tools/V3 _ Chap02.html # tag _ 18 _ 06 _ 02”rel = “ nofollow noReferrer”> 可移植性 你可以说 "${s#"${s%?}"}":

#!/bin/sh
m=bzzzM n=bzzzN
for s in \
'vv'  'w'   ''    'uu  ' ' uu ' '  uu' / \
'ab?' 'a?b' '?ab' 'ab??' 'a??b' '??ab' / \
'cd#' 'c#d' '#cd' 'cd##' 'c##d' '##cd' / \
'ef%' 'e%f' '%ef' 'ef%%' 'e%%f' '%%ef' / \
'gh*' 'g*h' '*gh' 'gh**' 'g**h' '**gh' / \
'ij"' 'i"j' '"ij' "ij'"  "i'j"  "'ij"  / \
'kl{' 'k{l' '{kl' 'kl{}' 'k{}l' '{}kl' / \
'mn$' 'm$n' '$mn' 'mn$$' 'm$$n' '$$mn' /
do  case $s in
(/) printf '\n' ;;
(*) printf '.%s. ' "${s#"${s%?}"}" ;;
esac
done

产出:

.v. .w. .. . . . . .u.
.?. .b. .b. .?. .b. .b.
.#. .d. .d. .#. .d. .d.
.%. .f. .f. .%. .f. .f.
.*. .h. .h. .*. .h. .h.
.". .j. .j. .'. .j. .j.
.{. .l. .l. .}. .l. .l.
.$. .n. .n. .$. .n. .n.

对于那些对纯 POSIX 方法感兴趣的人:

Https://github.com/spiralofhope/shell-random/blob/master/live/sh/scripts/string-fetch-last-character.sh

#!/usr/bin/env  sh


string_fetch_last_character() {
length_of_string=${#string}
last_character="$string"
i=1
until [ $i -eq "$length_of_string" ]; do
last_character="${last_character#?}"
i=$(( i + 1 ))
done


printf  '%s'  "$last_character"
}




string_fetch_last_character  "$string"