string - 在 Bash 中访问字符串的最后 x 个字符

标签 string bash extract

我发现使用 ${string:0:3} 可以访问字符串的前 3 个字符。是否有同样简单的方法来访问最后三个字符?

最佳答案

字符串的最后三个字符:

${string: -3}

${string:(-3)}

(注意第一种形式中 :-3 之间的空格)。

请引用Shell Parameter Expansion in the reference manual :

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

由于这个答案有一些常规 View ,让我添加一个可能来解决 John Rix的评论;正如他提到的,如果您的字符串长度小于 3,${string: -3} 将扩展为空字符串。如果,在这种情况下,你想要扩展string,你可以使用:

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

这使用了 ?: 三元 if 运算符,可以在 Shell Arithmetic 中使用。 ;因为如文档所述,偏移量是一个算术表达式,所以这是有效的。


POSIX 兼容解决方案的更新

前一部分给出了使用 Bash 时的最佳选择。如果你想以 POSIX shell 为目标,这里有一个选项(不使用管道或外部工具,如 cut):

# New variable with 3 last characters removed
prefix=${string%???}
# The new string is obtained by removing the prefix a from string
newstring=${string#"$prefix"}

这里要注意的主要事情之一是在参数扩展的 prefix 中使用引号。 POSIX ref 中提到了这一点(在本节末尾):

The following four varieties of parameter expansion provide for substring processing. In each case, pattern matching notation (see Pattern Matching Notation), rather than regular expression notation, shall be used to evaluate the patterns. If parameter is '#', '*', or '@', the result of the expansion is unspecified. If parameter is unset and set -u is in effect, the expansion shall fail. Enclosing the full parameter expansion string in double-quotes shall not cause the following four varieties of pattern characters to be quoted, whereas quoting characters within the braces shall have this effect. In each variety, if word is omitted, the empty pattern shall be used.

如果您的字符串包含特殊字符,这很重要。例如。 (破折号),

$ string="hello*ext"
$ prefix=${string%???}
$ # Without quotes (WRONG)
$ echo "${string#$prefix}"
*ext
$ # With quotes (CORRECT)
$ echo "${string#"$prefix"}"
ext

当然,这只有在事先知道字符数的情况下才有用,因为你必须在参数扩展中硬编码 ? 的数量;但在这种情况下,它是一个很好的可移植解决方案。

关于string - 在 Bash 中访问字符串的最后 x 个字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19858600/

相关文章:

python - 如何在 Python 中仅将字符串的特定部分转换为大写?

linux - CURL 用于访问需要从其他页面登录的页面

Python 提取/解压缩 RAR 文件错误

r - 提取字符串并填充到 r 中的其他列

python - 在python 3中查找字符串中某个单词的出现

c++ - 为什么字符串作为指针或字符串作为原始数组总是在重载函数中作为指针调用?

java - "(someString) Tj"到 java 字符串编码问题 (PDFBox)

linux - 通过 PIPE 发送 Unix/Linux SIGNAL

bash - 如何使用 awk 按列的最后一个值对列进行排序?

unix - 使用 sed 捕获第一个大写字母的单词