ody*_*sey 36 text-processing cut
我知道该cut命令可以打印n字符串的第一个字符,但如何选择最后一个n字符?
如果我有一个字符数可变的字符串,如何只打印字符串的最后三个字符。例如。
需要的“无限”输出是“ted” 需要的“987654”输出是“654” “123456789”需要的输出是“789”
G-M*_*ca' 61
为什么没有人给出明确的答案?
sed 's/.*\(...\)/\1/'
Run Code Online (Sandbox Code Playgroud)
……或者稍微不那么明显的
grep -o '...$'
Run Code Online (Sandbox Code Playgroud)
诚然,第二个的缺点是少于三个字符的行会消失;但问题没有明确定义这种情况下的行为。
Vol*_*gel 54
我们不应该只需要一个正则表达式或多个进程来计算字符数。
命令tail,通常用于显示文件的最后几行,有一个选项-c( --bytes),这似乎是解决此问题的正确工具:
$ printf 123456789 | tail -c 3
789
Run Code Online (Sandbox Code Playgroud)
(当您在 shell 中时,使用 mikeserv 的回答中的方法是有意义的,因为它可以节省启动进程tail。)
现在,您要求输入最后三个字符;这不是这个答案给你的:它输出最后三个字节!
只要每个字符是一个字节,tail -c就可以工作。因此,如果字符集是或变体ASCII,则可以使用它ISO 8859-1。
如果你有 Unicode 输入,就像普通UTF-8格式一样,结果是错误的:
$ printf 123??? | tail -c 3
??
Run Code Online (Sandbox Code Playgroud)
在这个例子中,使用UTF-8,希腊字符 alpha、beta 和 gamma 是两个字节长:
$ printf 123??? | wc -c
9
Run Code Online (Sandbox Code Playgroud)
该选项-m至少可以计算真正的 unicode 字符:
printf 123??? | wc -m
6
Run Code Online (Sandbox Code Playgroud)
好的,所以最后 6 个字节将为我们提供最后 3 个字符:
$ printf 123??? | tail -c 6
???
Run Code Online (Sandbox Code Playgroud)
所以,tail不支持处理一般字符,它甚至不尝试(见下文):它处理可变大小的行,但不处理可变大小的字符。
这么说吧:tail对于要解决的问题的结构来说是正确的,但是对于数据的类型是错误的。
进一步看,事实证明,你的coreutils GNU的基本工具,收集喜欢的sed,ls,tail并且cut,还没有完全国际化。这主要是关于支持Unicode。
例如,cut在这里使用而不是尾部来支持字符将是一个很好的候选者;它确实有处理字节或字符的选项,-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.
Run Code Online (Sandbox Code Playgroud)
另请参阅此回答到无法用UTF-8使用'砍-c`(`--characters`)?.
Dop*_*oti 37
如果您的文本位于名为 的 shell 变量中STRING,您可以在bash,zsh或mkshshell 中执行此操作:
printf '%s\n' "${STRING:(-3)}"
Run Code Online (Sandbox Code Playgroud)
或者
printf '%s\n' "${STRING: -3}"
Run Code Online (Sandbox Code Playgroud)
这也有利于与该语法来自的 ksh93 一起使用。
重点是:必须与 分开-,否则它就成为${var:-default}Bourne shell的操作符。
zsh或yashshell 中的等效语法是:
printf '%s\n' "${STRING[-3,-1]}"
Run Code Online (Sandbox Code Playgroud)
jas*_*yan 14
使用awk:
awk '{ print substr( $0, length($0) - 2, length($0) ) }' file
ted
654
789Run Code Online (Sandbox Code Playgroud)
mik*_*erv 11
如果字符串在变量中,您可以执行以下操作:
printf %s\\n "${var#"${var%???}"}"
Run Code Online (Sandbox Code Playgroud)
从$varlike的值中去除最后三个字符:
${var%???}
Run Code Online (Sandbox Code Playgroud)
...然后从$var所有东西的头部剥离,但刚刚剥离的内容如下:
${var#"${var%???}"}
Run Code Online (Sandbox Code Playgroud)
这种方法有其优点和缺点。从好的方面来说,它是完全 POSIX 可移植的,应该可以在任何现代 shell 中工作。另外,如果$var不包含至少三个字符没什么,但后\n打印ewline。再说一次,如果你想在这种情况下打印它,你需要一个额外的步骤,比如:
last3=${var#"${var%???}"}
printf %s\\n "${last3:-$var}"
Run Code Online (Sandbox Code Playgroud)
$last3只有在$var包含 3 个或更少字节时,这种方式才会为空。并且$var只替换$last3if$last3为空或unset- 我们知道这不是unset因为我们只是设置了它。
你可以这样做,但这有点......过度:
for s in unlimited 987654 123456789; do
rev <<< $s | cut -c 1-3 | rev
done
Run Code Online (Sandbox Code Playgroud)
ted
654
789
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
207414 次 |
| 最近记录: |