我有一个变量var在Bash脚本中持有一个字符串:
var
echo $var "some string.rtf"
我想删除这个字符串的最后四个字符,并将结果分配给一个新变量var2,以便
var2
echo $var2 "some string"
我该怎么做呢?
你可以用sed,
sed 's/.\{4\}$//' <<< "$var"
例子:
$ var="some string.rtf" $ var1=$(sed 's/.\{4\}$//' <<< "$var") $ echo $var1 some string
要从字符串末尾删除四个字符,请使用${var%????}。
${var%????}
要删除最后.之后并包括它在内的所有内容,请使用${var%.*}。
.
${var%.*}
有关更多参数展开,请参阅Bash的文档。
你可以这样做(在bash v4和更高版本中):
#!/bin/bash v="some string.rtf" v2=${v::-4} echo "$v --> $v2"
注意:macos使用bash 3。默认为X
使用变量展开/子字符串替换:
$ {var / %模式/替代} 如果var的后缀匹配Pattern,则用Replacement替换Pattern。
$ {var / %模式/替代}
如果var的后缀匹配Pattern,则用Replacement替换Pattern。
所以你可以这样做:
~$ echo ${var/%????/} some string
另外,
如果你总是有相同的4个字母
~$ echo ${var/.rtf/} some string
如果它总是以.xyz结尾:
.xyz
~$ echo ${var%.*} some string
你也可以使用字符串的长度:
~$ len=${#var} ~$ echo ${var::len-4} some string
或简单地echo ${var::-4}
echo ${var::-4}
对我有用的是:
echo "hello world" | rev | cut -c5- | rev # hello w
但我用它来修剪文件中的行,这就是为什么它看起来很尴尬。真正的用途是:
cat somefile | rev | cut -c5- | rev
cut只能让你从某个起始位置修剪,如果你需要可变长度的行,这是不好的。因此,这个解决方案反转(rev)字符串,现在我们关联到它的结束位置,然后使用前面提到的cut,并反转(同样是rev)它回到它原来的顺序。
cut
rev
我尝试了以下方法,对我很有效:
#! /bin/bash var="hello.c" length=${#var} endindex=$(expr $length - 4) echo ${var:0:$endindex}
输出:hel
hel
removechars(){ var="some string.rtf" size=${#var} echo ${var:0:size-4} } removechars var2=$?
一些字符串
希望下面的例子能有所帮助,
__abc0 __abc2 __abc1
start
len
read -p "Enter:" name echo ${name:0:$((${#name}-10))}
输出:
Enter:Siddharth Murugan Siddhar
注意:Bash 4.2增加了对负子字符串的支持
在这种情况下,您可以使用basename,假设您在要删除的文件上有相同的后缀。
basename -s .rtf "some string.rtf"
这将返回"some string"
如果你不知道后缀,并希望它删除后面的所有内容,包括最后一个点:
f=file.whateverthisis basename "${f%.*}"
输出“文件”
%表示切,。你砍的是*是通配符吗
首先,明确你的意图通常会更好。因此,如果你知道字符串以.rtf结尾,并且你想删除那个.rtf,你可以只使用var2=${var%.rtf}。这种方法的一个潜在有用的方面是,如果字符串不以.rtf结尾,则它根本不会改变;var2将包含var的未修改副本。
.rtf
var2=${var%.rtf}
如果你想删除一个文件名后缀,但不知道或不关心它到底是什么,你可以使用var2=${var%.*}删除从最后一个.开始的所有内容。或者,如果你只想保留到第一个的所有内容,但不包括.,你可以使用var2=${var%%.*}。如果只有一个.,这些选项的结果是相同的,但如果可能有多个.,你可以选择从字符串的哪一端开始工作。另一方面,如果字符串中根本没有., var2将再次成为var的不变副本。
var2=${var%.*}
var2=${var%%.*}
如果你真的想总是删除特定的数量字符,这里有一些选项。
你专门标记了这个bash,所以我们将从bash内置开始。工作时间最长的是我上面使用的相同的后缀删除语法:要删除四个字符,使用var2=${var%????}。或者只在第一个字符是圆点时删除四个字符,使用var2=${var%.???},它类似于var2=${var%.*},但只在圆点后面的部分恰好是三个字符时删除后缀。如您所见,要以这种方式计数字符,您需要为每个未知字符删除一个问号,因此对于较大的子字符串长度,这种方法会变得笨拙。
bash
var2=${var%????}
var2=${var%.???}
在较新的shell版本中,一个选项是子字符串提取:var2=${var:0:${#var}-4}。在这里,您可以在4的位置放置任何数字,以删除不同数量的字符。${#var}被字符串的长度所取代,因此这实际上是要求提取并保留(长度- 4)从第一个字符开始的字符(在索引0处)。使用这种方法,您将失去仅在字符串匹配模式时才进行更改的选项。只要字符串至少有四个字符,无论它的实际值是什么,副本都会包括除最后四个字符以外的所有字符。
var2=${var:0:${#var}-4}
4
${#var}
你可以去掉起始索引;它默认为0,所以你可以把它缩短为var2=${var::${#var}-4}。事实上,bash的新版本(特别是4+,这意味着MacOS附带的版本将无法工作)将负长度识别为字符的下标,从字符串的末尾开始计数。所以在这些版本中,你也可以去掉字符串长度的表达式:var2=${var::-4}。如果你保留字符串长度,但字符串短于四个字符,也会触发这个解释,因为${#var}-4是负的。例如,如果字符串有三个字符,${var:0:${#var}-4}将变成${var:0:-1},并且只删除最后一个字符。
var2=${var::${#var}-4}
var2=${var::-4}
${#var}-4
${var:0:${#var}-4}
${var:0:-1}
如果你实际上没有使用bash,而是使用其他posix类型的shell,那么使用%的基于模式的后缀删除仍然可以工作——即使在普通的旧破折号中,基于索引的子字符串提取也不能工作。Ksh和zsh都支持子字符串提取,但需要显式的0开始索引;ZSH还支持负结尾索引,而KSH需要长度表达式。注意,zsh索引从1开始的数组,但索引从0 如果使用这种bash兼容语法开始的字符串。但是zsh还允许您将标量参数视为字符数组,在这种情况下,子字符串语法使用基于1的计数,并将开始和(包括)结束位置放在用逗号分隔的括号中:var2=$var[1,-5]。
%
var2=$var[1,-5]
当然,您可以不使用内置的shell参数展开,而是运行一些实用程序来修改字符串并使用命令替换捕获其输出。有几个命令可以工作;一个是var2=$(sed 's/.\{4\}$//' <<<"$var")。
var2=$(sed 's/.\{4\}$//' <<<"$var")
这也可以做到:
... | head -c -1
-c, --bytes=[-]NUM print the first NUM bytes of each file; with the leading '-', print all but the last NUM bytes of each file
上面的答案不适合我,因为mac os x附带了不同版本的bash。
我像这样使用sed:
var2=`echo $var2 | sed 's/.$//'`
删除最后一个字符
var2=`echo $var2 | sed 's/..$//'`
删除最后2个字符。