通过删除最后 N 个字符来输出子字符串[重复]

问题描述 投票:0回答:4

如何通过管道传输字符串并从中删除一些字符?,例如:

$ echo forbes | ... -3
for
$ echo cucumber | ... -4
cucu
$ echo 1461624333 | .. -3 
1461624
...
etc.

我找不到在管道中使用

${str:0:-3}
语法的方法。

bash unix
4个回答
19
投票

通过管道传输到 sed:

$ echo forbes | sed 's/...$//'
for

这会匹配字符串的最后三个字符并将其删除(用空字符串替换)。

要参数化要删除的字符数,我们可以将其包装在一个小函数中:

pipesubstr () {
    sed "s/.\{$1\}$//"
}

使用方法如下:

$ echo forbes | pipesubstr 3
for
$ echo cucumber | pipesubstr 4
cucu
$ echo 1461624333 | pipesubstr 3
1461624

9
投票

使用

cut

$ echo "forbes" | cut -b 1-3
for

更新:

要从后面刮胡子,您可以这样做:

echo "forbes" | rev | cut -c (n+1)- | rev

其中

n
是您想要从末尾开始删除的字符数

echo "forbes" | rev | cut -c 4- | rev
for

9
投票

GNU

head
是另一种选择(从输入字符串中删除最后 N 个字符作为一个整体 - 即使它跨越多行):

# GNU `head` only (doesn't work with the `head` that comes with macOS)
# CAVEAT: -c operates on *bytes*, not characters.
$ printf '1461624333' | head -c -3   # drop last 3 chars.
1461624

请注意,如果您使用

echo
而不是
printf
,则必须考虑尾随
\n
,因此您必须将
1
添加到计数中(并且输出不会有尾随
\n 
)。

警告:

head -c
,尽管选项名称很短,但操作于字节而不是字符,因此仅适用于单字节编码,例如 ASCII 和扩展 ASCII 变体(例如,ISO-8859=1),因此可靠地使用UTF-8只有当最后 N 个字符恰好都是 ASCII 范围字符时,结果才会符合预期。
使用选项名称的long形式,
--bytes
,使这个限制更加明显。


顺便说一句:

  • 如果您也想在 macOS 上使用 GNU 实用程序,您可以通过 Homebrew 安装它们:
    brew install coreutils

    默认情况下,这会使用
    g
    前缀(例如
    ghead
    )安装它们,以免覆盖内置实用程序,但您可以按照安装时打印的说明中的说明修改
    PATH
    来覆盖后者。

1
投票

awk
解决方案(从输入中的每一行
中删除最后一个
n字符):

$ echo '1461624333' | awk -v n=3 '{ print substr($0, 1, length($0)-n) }' # drop last 3 1461624

警告: 并非所有 awk

 实现都支持区域设置;例如,OS X 10.11.4 上的 BSD 
awk
 不是:

$ echo 'usä' | awk -v n=1 '{ print substr($0, 1, length($0)-n) }' us? # !! on OSX, mistakenly returns the first byte of multi-byte UTF8 char. 'ä'
    
© www.soinside.com 2019 - 2024. All rights reserved.