我想删除字符串的最后一个字符,我尝试了这个小脚本:

#! /bin/sh 

t="lkj"
t=${t:-2}
echo $t


但它显示“ lkj”,我在做什么错? />

#1 楼

在POSIX Shell中,语法${t:-2}表示不同的东西-如果设置了t且不为null,则扩展为t的值,否则扩展为2的值。要通过参数扩展修剪单个字符,您可能需要的语法为${t%?}

请注意,在ksh93bashzsh${t:(-2)}${t: -2}(请注意空格)作为子字符串扩展是合法的,但可能不是您想要的,因为它们返回从末尾开始2个字符的位置开始的子字符串(即,它删除字符串i的第一个字符ijk)。

请参见Bash参考手册以获取更多信息:


Bash参考手册– Shell参数扩展


评论


您是否愿意解释“%”背后的魔力是什么? ?

–评估
16年4月14日在15:36

@afraisse $ {parameter%word}删除最短的后缀模式匹配词-请参见man bash的“参数扩展”部分

–钢驾驶员
16年4月14日在18:15

这对于Bash 4.1.2来说效果很好:$ {t%?}对于受CentOS / RHEL 6.x困扰的人们

–Joey T
17年1月12日在23:04

#2 楼

使用bash 4.2及更高版本,您可以执行以下操作:

${var::-1}


示例:

$ a=123
$ echo "${a::-1}"
12


请注意,较早的版本bash(例如,在OS X上为bash 3.2.5),则应在冒号之间和之后留空格:

${var: : -1}


评论


这适用于bash 4.2-alpha及更高版本,可惜我可以访问的版本更早。 :-/

– h.j.k.
2014年7月14日在3:46

@iamaziz:从bash更改日志中,仅在bash 4.2中添加了$ {var:offset:lenght}中的负长度。也许OSX为bash添加了自己的补丁。

–cuonglm
16年5月8日在5:59

@cuonglm都不起作用:/

–iamaziz
16年5月8日在6:59

在Mac上不起作用。

– Shinzou
17年8月6日在6:57

MACsters,请小看Russ的回答

– P i
18年6月21日在1:55

#3 楼

使用sed的速度应与

sed 's/.$//'

一样快,那么您的单回声就是echo ljk | sed 's/.$//'
使用它,一线字符串可以是任意大小。 br />

评论


请注意,在一般情况下,它不会删除字符串的最后一个字符,而是删除字符串的每一行的最后一个字符。

–StéphaneChazelas
16年2月1日在10:23

#4 楼

用于从不使用nsed的行中删除最后一个awk字符:

> echo lkj | rev | cut -c (n+1)- | rev


,例如,您可以使用以下命令删除最后一个one character

> echo lkj | rev | cut -c 2- | rev

> lk


rev联机帮助页:


Description
rev实用程序将指定的文件复制到标准输出,
/>反转每一行中的字符顺序。如果没有指定文件,则将读取标准输入。


UPDATE:

如果您不知道文件的长度字符串,请尝试:

$ x="lkj"
$ echo "${x%?}"
lk


#5 楼

取决于外壳的一些选项:


POSIX:t=${t%?}

t=`expr " $t" : ' \(.*\).'`

zsh / yash:t=${t[1,-2]}

bash / zsh:t=${t:0:-1}

ksh93 / bash / zsh / mksh:t=${t:0:${#t}-1}


ksh93 / bash / zsh / mksh:t=${t/%?}

ksh93:t=${t/~(E).$/}

es:@ {t=} ~~ $t *?


请注意,尽管所有人都应该剥离最后一个字符,但您会发现一些实现(那些实现不支持多字节字符)改为去除最后一个字节(如果最后一个字符是多字节,则可能会破坏最后一个字符)。

expr变体假定$t的结尾不超过一个换行符。如果结果字符串最终是0(在某些实现中甚至是000甚至-0),它也会返回非零退出状态。如果字符串包含无效字符,也可能会产生意外结果。

评论


尼斯和彻底!但是...我想所有这些shell都支持POSIX,所以每个人都应该使用那个外壳来实现最大的可移植性。字符数最少!

–俄罗斯
16-09-16在3:20

@ Russ,t = $ {t%?}不是Bourne,但如今您不太可能遇到Bourne壳。 $ {t%?}确实可以在所有其他代码中使用。

–StéphaneChazelas
16 Sep 16'6:53

没有提供鱼壳选项!这些天可能比ksh93更流行...

–rien333
17年11月18日在1:21

@ rien333。我将等待接口稳定下来。鱼正在开发中。引入Q2A时未发布引入内置字符串的2.3.0。在我正在测试的版本上,您需要字符串替换-r'(?s)。\ z'''-$ t(我希望他们想要更改它,他们应该更改标志他们传递给PCRE)或更复杂的文件。它也不能很好地处理换行符,而且我知道他们也计划对此进行更改。

–StéphaneChazelas
17年11月18日在8:10

@Timo,不确定您的意思。我提供的解决方案都不是特定于bash的。 bash AFAIK发明的唯一一个是t = $ {t:0:-1}(扩展了$ {var:offset:length} ksh93运算符)。对于每个,我都给出了支持它的shell。您可以使用来自Bourne / POSIX的和现代的sh。

–StéphaneChazelas
20 Nov 16在14:02



#6 楼

几乎可以肯定,最便携,最短的答案是:

${t%?}

这适用于bash,sh,ash,dash,dashing,busybox / ash,zsh,ksh等。

它通过使用老式的shell参数扩展来工作。具体来说,%指定要删除与全局模式t相匹配的参数?的最小匹配后缀(即:任何字符)。

有关更多(更详细)信息,请参见此处的“删除最小后缀模式”。说明和更多背景。另请参见“参数扩展”下的外壳文档(例如:man bash)。


作为旁注,如果要删除第一个字符,则可以使用${t#?},因为#从字符串的前面(前缀)而不是后面(后缀)匹配。

还值得注意的是,%#都有%%##版本,它们匹配最长的版本。给定的模式,而不是最短的模式。不过,在这种情况下,${t%%?}${t##?}的作用与它们的单个运算符相同(因此,请不要添加无用的额外字符)。这是因为给定的?模式仅匹配单个字符。混合使用*和一些非通配符,使用%%##会使事情变得更有趣。

了解参数扩展,或者至少知道它们的存在并知道如何查找它们,对于编写和解密多种口味的shell脚本。对于许多人来说,参数扩展通常看起来像奥术外壳的伏都教,因为……好吧……它们是奥术外壳的伏都教(尽管如果您知道要寻找“参数扩展”,也有很好的记录)。但是,当您卡在外壳中时,绝对可以将它放在工具带中。

评论


简短有趣,可在MacOS和Linux上使用!

– dbernard
19年8月14日在1:29

#7 楼

t=lkj
echo ${t:0:${#t}-1}


您得到一个从0到字符串长度-1的子字符串。但是请注意,此减法是bash特定的,并且不适用于其他shell。例如,dash甚至无法解析

echo ${t:0:$(expr ${#t} - 1)}


例如,在Ubuntu上,/bin/shdash

#8 楼

您还可以使用head打印出除最后一个字符以外的所有字符。

$ s='i am a string'
$ news=$(echo -n $s | head -c -1)
$ echo $news
i am a strin


但是不幸的是,某些版本的head不包括前导-选项。 OS X随附的head就是这种情况。

#9 楼

一些改进。要删除多个字符,可以添加多个问号。例如,要从变量$SRC_IP_MSG中删除最后两个字符,可以使用:

SRC_IP_MSG=${SRC_IP_MSG%??}


#10 楼

使用正则表达式很容易做到:

n=2
echo "lkj" | sed "s/\(.*\).\{$n\}//"


#11 楼

只是为了完成纯bash的一些可能用法:

#!/bin/bash

# Testing substring removal
STR="Exemple string with trailing whitespace "
echo "'$STR'"
echo "Removed trailing whitespace: '${STR:0:${#STR}-1}'"
echo "Removed trailing whitespace: '${STR/%\ /}'"


第一种语法是字符串中的子字符串,语法是${STRING:OFFSET:LENGTH}
对于第二种语法,请注意%符号,它表示“从行尾开始”,语法为${STRING/PATTERN/SUBSTITUTION}

,这是上述两种较短的形式

echo "Removed trailing whitespace: '${STR::-1}'"
echo "Removed trailing whitespace: '${STR%\ }'"


请再次注意%符号,意思是'从参数的末尾删除(即用''替换)最短的匹配模式(此处由转义空格'\'表示),此处命名为STR

#12 楼

由于我们也可以在命令行或shell脚本中使用php。
有时对外科手术分析很有用。

php -r "echo substr('Hello', 0, -1);" 
// Output hell


带管道:

echo "hello" | php -r "echo substr(trim(fgets(STDIN)), 0, -1);"
// Output hell


#13 楼

在ksh中:

echo ${ORACLE_SID/%?/}