我在一个Bash脚本中有一个字符串变量var
:
echo $var
"some string.rtf"
我想删除这个字符串的最后四个字符,并将结果分配给一个新变量var2
,以便:
echo $var2
"some string"
我该怎么做?
我在一个Bash脚本中有一个字符串变量var
:
echo $var
"some string.rtf"
我想删除这个字符串的最后四个字符,并将结果分配给一个新变量var2
,以便:
echo $var2
"some string"
我该怎么做?
#!/bin/bash
v="some string.rtf"
v2=${v::-4}
echo "$v --> $v2"
注意:macOS 默认使用 bash 3.x
bash
的4及以上版本,但在早期版本中,您可以使用稍微冗长一些的${v::${#v}-4}
。 - chepner${v::-4}
会报错“zsh:期望闭括号”。但是@fredtantini下面的答案${v:0:-4}
可以正常工作。 - Pierre D${var#????}
。 - tripleee首先,在表达意图时通常最好是明确的。所以,如果您知道字符串以.rtf
结尾,并且您想要删除它,您可以使用var2=${var%.rtf}
。这种方法的一个潜在有用之处是,如果该字符串不以.rtf
结尾,则根本不会被更改; var2
将包含var
的未修改副本。
如果您想要删除文件名后缀但并不知道或关心其确切内容,您可以使用var2=${var%.*}
来删除从最后一个.
开始的所有内容。或者,如果您只想保留第一个.
之前的所有东西而不包括它,您可以使用var2=${var%%.*}
。如果字符串中只有一个.
,那么这两个选项具有相同的结果,但是如果可能存在多个,您可以选择从哪一端对字符串进行操作。另一方面,如果字符串中根本没有.
,那么var2
将再次成为var
的未修改副本。
如果您真的想始终删除特定数量的字符,这里有一些选项。
您特别标记了这个问题与bash
有关,因此我们首先介绍bash内置命令。其中已经使用最久的是我上面使用的相同后缀删除语法:var2=${var%????}
,用于删除四个字符。或者只有第一个字符是点时才删除四个字符,使用var2=${var%.???}
,这类似于var2=${var%.*}
,但只有在点后面的部分恰好为三个字符时才删除后缀。如您所见,要以这种方式计算字符数,您需要为每个未知字符删除一个问号,因此对于较长的子字符串长度,这种方法变得棘手。var2=${var:0:${#var}-4}
。在这里,您可以将任何数字放在4
的位置上,以删除不同数量的字符。 ${#var}
被替换为字符串的长度,因此实际上是要求提取并保留从第一个字符(索引为0)开始的(length-4)个字符。使用此方法,您失去了仅在字符串匹配模式时进行更改的选项。只要字符串至少有四个字符,无论其实际值如何,复制都将包括除其最后四个字符之外的所有字符。您可以省略开始索引;它默认为0,因此您可以将其缩短为 var2=${var::${#var}-4}
。实际上,较新版本的 bash(特别是 4+ 版本,这意味着随 MacOS 附带的版本无法工作)将负长度识别为要停止的字符索引,从字符串末尾开始计数。因此,在这些版本中,您也可以摆脱字符串长度表达式:var2=${var::-4}
。如果字符串长度小于四个字符,则也会触发此解释,因为此时${#var}-4
将是负数。例如,如果字符串有三个字符,则${var:0:${#var}-4}
变成了${var:0:-1}
,只删除了最后一个字符。如果你并不使用 bash 而是其他的 POSIX 类型 shell,基于模式的后缀删除操作仍然适用——即使在旧版 dash 中,其中的基于索引的子字符串提取操作则不支持。Ksh 和 zsh 都支持子字符串提取,但需要显式的 0 开始索引;zsh 还支持负数结尾索引,而ksh需要长度表达式。请注意,zsh 从 1 开始索引数组,但如果你使用此兼容bash的语法,则对于字符串也是从 0 开始索引。但是,zsh 还允许您将标量参数视为字符数组,在这种情况下,子字符串语法使用基于 1 的计数,并将起始位置和(包括)终止位置放在以逗号分隔的方括号中:var2=$var[1,-5]。${__repo%.git}
可能会更清晰,因为您知道要删除哪四个字符。如果字符串不以.git
结尾,则也不会删除任何内容,因此即使__repo
的值由于某种原因不包括后缀,它也可以正常工作。 - Mark Reedcut -c -4
并不是你想象中的那样。它只会从字符串的第一个字符打印到第四个字符,这里只会简单地输出 some
。你无法使用 cut
实现这一点。 - Atralbexport HOSTNAME=hostname; echo "/lfs/${HOSTNAME::-13}/0/brando9"
- Charlie Parkerrev
反转行而不是字符串。echo $SOME_VAR | rev | ...
可能不会按照人们的期望运行。 - Mohammad Nasirifarvar2=$(echo $var | rev | cut -c5- | rev)
,但是是的,从技术上讲,这个命令只适用于单行。如果您不想将每一行作为单独的字符串处理,则可能无法按预期工作。 - Zbyszekecho -e 'abc\ndef' | rev
显示rev将每行反转,因此,如果只有一行,它将反转该行。而且如果给出的只是没有\n的字符,例如 echo -n abc|rev
,它仍然会将其反转。那么你的问题是,如果字符串中有 \n,它会将其视为新行,并在 \n 字符之间反转而不是跨越它们吗?问题的示例中没有换行符。你有没有想过使用 cat file | rev
,但这已经不再是他们的答案了? - barlop使用变量扩展/子字符串替换:
${var/%Pattern/Replacement}
如果 var 的后缀匹配 Pattern,则将 Replacement 替换为 Pattern。
因此,您可以执行以下操作:
~$ echo ${var/%????/}
some string
如果您需要翻译,请告诉我需要翻译成哪种语言。
或者,
如果您一直使用相同的4个字母,
~$ echo ${var/.rtf/}
some string
.xyz
结尾:~$ echo ${var%.*}
some string
您也可以使用字符串的长度:
~$ len=${#var}
~$ echo ${var::len-4}
some string
echo ${var::-4}
len=${#var}; echo ${var::len-4}
可以缩写为 echo ${var:0:-4}
:-) 编辑:或者如 @iyonizer 指出的那样,只需使用 echo ${var::-4}
... - anishsane您可以使用sed命令,
sed 's/.\{4\}$//' <<< "$var"
例子:
$ var="some string.rtf"
$ var1=$(sed 's/.\{4\}$//' <<< "$var")
$ echo $var1
some string
var2
? - a06e这也可以完成工作:
... | 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
echo "$v" | head -c -1
在 BSD head 中会出现 "head: illegal byte count -- -1" 的错误。
使用 GNU head (ghead),echo "$v" | ghead -c -1
不会删除任何字符,结果为 "some string.rtf%"。
ghead -c -1 <<<'some string.rtf'
也不会删除任何字符。
最后,为了确认没有任何问题,wc -c <<<"$v"; wc -c <<<"$(ghead -c -1 <<<"$v")"
显示两者都有 16 个字节。你必须使用 head/ghead -c -2
。对于那些感兴趣的人,ghead --version
会输出 "head (GNU coreutils) 9.0"。 - SgtPooki希望以下示例能够帮到您:
echo ${name:0:$((${#name}-10))}
--> ${name:start:len}
name
是变量。start
是要删除字符串的起始点。len
是要删除的字符串长度。例如:
read -p "Enter:" name
echo ${name:0:$((${#name}-10))}
输出:
Enter:Siddharth Murugan
Siddhar
echo "{${name:0:${#name} - 1}}"
来删除最后一个字符并避免“子字符串表达式<0”错误。 - Clemens在这种情况下,假设你要删除的文件具有相同的后缀名,你可以使用basename。
示例:
basename -s .rtf "some string.rtf"
这将返回"some string"
如果您不知道后缀,并希望删除最后一个点及其后面的所有内容:
f=file.whateverthisis
basename "${f%.*}"
输出 "file"
% 表示剪切,. 是要剪切的内容,* 是通配符。
#! /bin/bash
var="hello.c"
length=${#var}
endindex=$(expr $length - 4)
echo ${var:0:$endindex}
hel
export HOSTNAME=hostname; echo "/lfs/${HOSTNAME::-13}/0/brando9"
- Charlie Parker