仅打印字符串的最后 3 个字符的命令

仅打印字符串的最后 3 个字符的命令

我知道该cut命令可以打印字符串的第一个n字符,但如何选择最后一个n字符?

如果我有一个字符数可变的字符串,如何只打印该字符串的最后三个字符。例如。

所需的“无限”输出是“ted”
需要的“987654”输出是“654”
“123456789”需要的输出是“789”

答案1

为什么没有人给出明显的答案?

sed 's/.*\(...\)/\1/'

……或者稍微不太明显的

grep -o '...$'

诚然,第二个有一个缺点,即少于三个字符的行会消失;但问题没有明确定义这种情况的行为。

答案2

保持简单 - 尾巴

我们不需要正则表达式或多个进程来计算字符。
该命令tail,常用于显示最后一个线文件的,有一个选项-c( --bytes),这似乎是执行此操作的正确工具:

$ printf 123456789 | tail -c 3
789

(当您在 shell 中时,使用 mikeserv 的答案中的方法是有意义的,因为它可以节省启动进程tail。)

真正的 Unicode 字符?

现在,你要求最后三个人物;这不是这个答案给你的:它输出最后三个字节

只要每个字符都是一个字节,tail -c就可以了。所以只要字符集是就可以使用ASCII,ISO 8859-1或变体。

如果你有 Unicode 输入,就像常见的那样UTF-8格式错误,结果错误:

$ printf 123αβγ | tail -c 3
�γ

在此示例中,使用UTF-8,希腊字符 alpha、beta 和 gamma 的长度为两个字节:

$ printf 123αβγ | wc -c  
9

该选项-m至少可以计算真实的 unicode 字符:

printf 123αβγ | wc -m
6

好的,最后 6 个字节将为我们提供最后 3 个字符:

$ printf 123αβγ | tail -c 6
αβγ

因此,tail不支持处理一般字符,它甚至不尝试(见下文):它处理可变大小的行,但不处理可变大小的字符。

让我们这样说:tail对于要解决的问题的结构来说是正确的,但对于数据的类型来说是错误的。

GNU 核心工具

进一步来看,GNU coreutils(诸如sedlstailcut等基本工具的集合)尚未完全国际化。主要是支持Unicode。
例如,cut在这里使用 代替 tail 来支持字符是一个很好的选择;它确实有处理字节或字符的选项,-c( --bytes) 和-m( --chars);

只是-m/--chars
cut (GNU coreutils) 8.212013 版本开始还
没有实现!

info cut

`-c CHARACTER-LIST'
`--characters=CHARACTER-LIST'
     Select for printing only the characters in positions listed in CHARACTER-LIST.  
     The same as `-b' for now, but internationalization will change that.


另请参阅此回答无法将 `cut -c` (`--characters`) 与 UTF-8 一起使用?

答案3

如果您的文本位于名为 的 shell 变量中,则STRING可以在bashzsh或shell 中执行此操作:mkshbusybox ash

printf '%s\n' "${STRING:(-3)}"

或者

printf '%s\n' "${STRING: -3}"

这也有利于与该语法的来源 ksh93 一起使用。

要点是 必须:与 分开-,否则它就成为${var:-default}Bourne shell 的操作符。

zsh或shell中的等效语法yash是:

printf '%s\n' "${STRING[-3,-1]}"

答案4

如果字符串位于变量中,您可以执行以下操作:

printf %s\\n "${var#"${var%???}"}"

这会从 like 的值中删除最后三个字符$var

${var%???}

...然后从头部剥离$var所有东西刚刚被剥离的东西是这样的:

${var#"${var%???}"}

这种方法有其优点和缺点。从好的方面来说,它是完全 POSIX 移植的,并且应该可以在任何现代 shell 中工作。另外,如果$var不包含至少三个字符没有什么但尾随的\newline 被打印。话又说回来,如果你在这种情况下打印,您需要一个额外的步骤,例如:

last3=${var#"${var%???}"}
printf %s\\n "${last3:-$var}"

这样,只有包含 3 个或更少的字节$last3时才为空。 $varAnd$var只会被替换为$last3if$last3为空或unset- 我们知道它不是,unset因为我们刚刚设置了它。

相关内容