Bash的最后一个指数

时间:2013-04-22 17:46:57

标签: bash shell pattern-matching

对于蹩脚的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 个答案:

答案 0 :(得分:23)

标题为“变量替代”的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

答案 1 :(得分:8)

$ a="artifact-1.2.3.zip"; a="${a#*-}"; echo "${a%.*}"

'# 模式'删除模式,只要它与$a开头匹配即可。 pattern 的语法类似于文件名匹配中使用的语法。 在我们的例子中,

  • *是任何字符序列。
  • -表示文字破折号。
  • 因此,#*-会匹配第一个短划线的所有内容。
  • 因此${a#*-}扩展为$a扩展到的任何内容, 除了从扩展中删除artifact-之外, 留下1.2.3.zip

同样,“% 模式”会删除模式,只要它与扩展的 end 匹配即可。 在我们的例子中,

  • .一个字面点。
  • *任何字符序列。
  • 因此,%.*包括 last 点到字符串末尾的所有内容。
  • 因此,如果$a扩展为1.2.3.zip, 然后${a%.*}扩展为1.2.3

完成工作。

此手册页内容如下(至少在我的机器上,YMMV):

       ${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。 如果他们不懂手册, 然后发布另一个问题。

答案 2 :(得分:3)

使用Bash RegEx功能:

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

答案 3 :(得分: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的更多信息。