Bash最后一个索引
对不起,这个蹩脚的bash问题,但我似乎无法解决。Bash最后一个索引
我有以下简单的例子:
我有可变像
artifact-1.2.3.zip
我想得连字符和点的最后一个指数之间的子串(包括独家)。
我的bash技能不太强。我有以下几点:
a="artifact-1.2.3.zip"; b="-"; echo ${a:$(($(expr index "$a" "$b" + 1) - $(expr length "$b")))}
生产:
1.2.3.zip
如何删除.zip
部分呢?
$ a="artifact-1.2.3.zip"; a="${a#*-}"; echo "${a%.*}"
“#
模式”删除模式,只要它符合开始的$a
。 模式的语法与文件名匹配中使用的语法相似。 在我们的例子中,
-
*
是任何字符序列。 -
-
表示字面短划线。 - 因此
#*-
匹配所有内容,包括第一个短划线。 - 因此
${a#*-}
扩展到任何$a
将扩大至, 除了artifact-
从扩张取出, 留给我们1.2.3.zip
。
类似地,“%
图案”删除图案,只要它的膨胀端匹配。 在我们的案例中,
-
.
字面点。 -
*
任何字符序列。 - 因此
%.*
就是一切,包括最后的点直到字符串的末尾。 - 因此,如果
$a
扩大到1.2.3.zip
, 然后${a%.*}
扩大到1.2.3
。
工作完成。
本手册页内容如下(至少在我的机器,情况因人而异上):
${parameter#word} ${parameter##word} The word is expanded to produce a pattern just as in pathname expansion. If the pattern matches the beginning of the value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pattern (the ``#'' case) or the longest matching pattern (the ``##'' case) deleted. If parameter is @ or *, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list. ${parameter%word} ${parameter%%word} The word is expanded to produce a pattern just as in pathname expansion. If the pattern matches a trailing portion of the expanded value of parameter, then the result of the expansion is the expanded value of parameter with the shortest matching pat- tern (the ``%'' case) or the longest matching pattern (the ``%%'' case) deleted. If parameter is @ or *, the pattern removal operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the pattern removal operation is applied to each member of the array in turn, and the expansion is the resultant list.
HTH!
编辑
荣誉对@ x4d了详细的解答。 尽管如此,仍然认为人们应该RTFM。 如果他们不明白手册, 然后张贴另一个问题。
我认为你可以这样做:
string=${a="artifact-1.2.3.zip"; b="-"; echo ${a:$(($(expr index "$a" "$b" + 1) - $(expr length "$b")))}}
substring=${string:0:4}
最后一步的最后4个字符从字符串中删除。还有一些关于here的更多信息。
+1:虽然它会将我和三个字母的扩展名绑定在一起。我会接受bobbogo的回答。谢谢! – carlspring 2013-04-22 17:55:11
谢谢,没问题,这不是一个非常便携的解决方案,但我喜欢让事情简单:)。 Bobbogo的解决方案是要走的路。 – James 2013-04-22 17:56:36
使用bash正则表达式的功能:
>str="artifact-1.2.3.zip"
[[ "$str" =~ -(.*)\.[^.]*$ ]] && echo ${BASH_REMATCH[1]}
标题bash
手册页节 “变量替换” 使用${var#pattern}
,${var##pattern}
,${var%pattern}
和${var%%pattern}
描述。
假设你有一个叫filename
变量,例如,
filename="artifact-1.2.3.zip"
那么,下面是基于模式的提取:
% echo "${filename%-*}"
artifact
% echo "${filename##*-}"
1.2.3.zip
为什么我用##
代替#
?
如果文件名可能可能包含内破折号,如:
filename="multiple-part-name-1.2.3.zip"
然后比较两个以下取代:
% echo "${filename#*-}"
part-name-1.2.3.zip
% echo "${filename##*-}"
1.2.3.zip
一旦已经提取出的版本和扩展,以隔离的版本,使用方法:
% verext="${filename##*-}"
% ver="${verext%.*}"
% ext="${verext##*.}"
% echo $ver
1.2.3
% echo $ext
zip
我也会试试这个!感谢您的详细描述。 – carlspring 2013-04-22 18:35:23
好又简单,谢谢! – carlspring 2013-04-22 17:54:35
这里列出的任何解释或相关文档会更好。 – Judking 2015-05-13 08:52:13
RTFM。公平的说,手册页非常大。在该文件中查找两个连续的哈希,并且您将位于右侧区域(_less_中的'/ ##'命令) – bobbogo 2015-05-13 09:50:19