2013-04-22 89 views
6

对不起,这个蹩脚的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部分呢?

回答

4
$ 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。 如果他们不明白手册, 然后张贴另一个问题。

+0

好又简单,谢谢! – carlspring 2013-04-22 17:54:35

+5

这里列出的任何解释或相关文档会更好。 – Judking 2015-05-13 08:52:13

+0

RTFM。公平的说,手册页非常大。在该文件中查找两个连续的哈希,并且您将位于右侧区域(_less_中的'/ ##'命令) – bobbogo 2015-05-13 09:50:19

0

我认为你可以这样做:

string=${a="artifact-1.2.3.zip"; b="-"; echo ${a:$(($(expr index "$a" "$b" + 1) - $(expr length "$b")))}} 

substring=${string:0:4} 

最后一步的最后4个字符从字符串中删除。还有一些关于here的更多信息。

+0

+1:虽然它会将我和三个字母的扩展名绑定在一起。我会接受bobbogo的回答。谢谢! – carlspring 2013-04-22 17:55:11

+0

谢谢,没问题,这不是一个非常便携的解决方案,但我喜欢让事情简单:)。 Bobbogo的解决方案是要走的路。 – James 2013-04-22 17:56:36

3

使用bash正则表达式的功能:

>str="artifact-1.2.3.zip" 
[[ "$str" =~ -(.*)\.[^.]*$ ]] && echo ${BASH_REMATCH[1]} 
21

标题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 
+0

我也会试试这个!感谢您的详细描述。 – carlspring 2013-04-22 18:35:23

相关问题