我知道该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(诸如sed
、ls
、tail
和cut
等基本工具的集合)尚未完全国际化。主要是支持Unicode。
例如,cut
在这里使用 代替 tail 来支持字符是一个很好的选择;它确实有处理字节或字符的选项,-c
( --bytes
) 和-m
( --chars
);
只是-m
/--chars
从
cut (GNU coreutils) 8.21
2013 版本开始还
没有实现!
从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.
答案3
如果您的文本位于名为 的 shell 变量中,则STRING
可以在bash
、zsh
或shell 中执行此操作:mksh
busybox 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
不包含至少三个字符没有什么但尾随的\n
ewline 被打印。话又说回来,如果你想在这种情况下打印,您需要一个额外的步骤,例如:
last3=${var#"${var%???}"}
printf %s\\n "${last3:-$var}"
这样,只有包含 3 个或更少的字节$last3
时才为空。 $var
And$var
只会被替换为$last3
if$last3
为空或unset
- 我们知道它不是,unset
因为我们刚刚设置了它。