Bash last index of Bash last index of shell shell

Bash last index of


The bash man page section titled "Variable Substitution" describes using ${var#pattern}, ${var##pattern}, ${var%pattern}, and ${var%%pattern}.

Assuming that you have a variable called filename, e.g.,

filename="artifact-1.2.3.zip"

then, the following are pattern-based extractions:

% echo "${filename%-*}"artifact% echo "${filename##*-}"1.2.3.zip

Why did I use ## instead of #?

If the filename could possibly contain dashes within, such as:

filename="multiple-part-name-1.2.3.zip"

then compare the two following substitutions:

% echo "${filename#*-}"part-name-1.2.3.zip% echo "${filename##*-}"1.2.3.zip

Once having extracted the version and extension, to isolate the version, use:

% verext="${filename##*-}"% ver="${verext%.*}"% ext="${verext##*.}"% echo $ver1.2.3% echo $extzip


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

#pattern’ removes pattern so long as it matches the beginning of $a.The syntax of pattern is similar to that used in filename matching.In our case,

  • * is any sequence of characters.
  • - means a literal dash.
  • Thus #*- matches everything up to, and including, the first dash.
  • Thus ${a#*-} expands to whatever $a would expand to,except that artifact- is removed from the expansion,leaving us with 1.2.3.zip.

Similarly, ‘%pattern’ removes pattern so long as it matches the end of the expansion.In our case,

  • . a literal dot.
  • * any sequence of characters.
  • Thus %.* is everything including the last dot up to the end of the string.
  • Thus if $a expands to 1.2.3.zip,then ${a%.*} expands to 1.2.3.

Job done.

The man page content for this is as follows (at least on my machine, 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!

EDIT

Kudos to @x4d for the detailed answer.Still think people should RTFM though.If they don't understand the manual,then post another question.


Using Bash RegEx feature:

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