#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
但它显示“ lkj”,我在做什么错? />
#1 楼
在POSIX Shell中,语法${t:-2}
表示不同的东西-如果设置了t
且不为null,则扩展为t
的值,否则扩展为2
的值。要通过参数扩展修剪单个字符,您可能需要的语法为${t%?}
请注意,在
ksh93
,bash
或zsh
,${t:(-2)}
或${t: -2}
(请注意空格)作为子字符串扩展是合法的,但可能不是您想要的,因为它们返回从末尾开始2个字符的位置开始的子字符串(即,它删除字符串i
的第一个字符ijk
)。请参见Bash参考手册以获取更多信息:
Bash参考手册– Shell参数扩展
#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 楼
用于从不使用n
或sed
的行中删除最后一个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/sh
是dash
#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/%?/}
评论
您是否愿意解释“%”背后的魔力是什么? ?
–评估
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