Bash 的最后一个索引

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16153446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 05:14:46  来源:igfitidea点击:

Bash last index of

bashshellpattern-matching

提问by carlspring

Sorry for the lame bash question, but I can't seem to be able to work it out.

很抱歉这个蹩脚的 bash 问题,但我似乎无法解决。

I have the following simple case:

我有以下简单案例:

  • I have variable like artifact-1.2.3.zip

  • I would like to get a sub-string between the hyphen and the last index of the dot (both exclusive).

  • 我有像这样的变量 artifact-1.2.3.zip

  • 我想在连字符和点的最后一个索引(都是独占的)之间获得一个子字符串。

My bash skill are not too strong. I have the following:

我的 bash 技能不是太强。我有以下几点:

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

Producing:

生产:

1.2.3.zip

How do I remove the .zippart as well?

我如何删除.zip零件?

采纳答案by bobbogo

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

#pattern' removes patternso long as it matches the beginningof $a. The syntax of patternis similar to that used in filename matching. In our case,

#模式”中移除了图案,只要比赛开始$a模式的语法类似于文件名匹配中使用的语法。在我们的例子中,

  • *is any sequence of characters.
  • -means a literal dash.
  • Thus #*-matches everything up to, and including, the firstdash.
  • Thus ${a#*-}expands to whatever $awould expand to, except that artifact-is removed from the expansion, leaving us with 1.2.3.zip.
  • *是任何字符序列。
  • -表示字面破折号。
  • 因此#*-匹配所有内容,包括第一个破折号。
  • 因此${a#*-}扩展到任何$a将扩展到的东西,除了artifact-从扩展中删除之外,留下1.2.3.zip.

Similarly, ‘%pattern' removes patternso long as it matches the endof the expansion. In our case,

类似地,只要匹配扩展的结尾,' %pattern' 就会删除模式。在我们的例子中,

  • .a literal dot.
  • *any sequence of characters.
  • Thus %.*is everything including the lastdot up to the end of the string.
  • Thus if $aexpands to 1.2.3.zip, then ${a%.*}expands to 1.2.3.
  • .一个字面意思。
  • *任何字符序列。
  • 因此%.*,包括最后一个点到字符串末尾的所有内容都是如此。
  • 因此,如果$a扩展为1.2.3.zip,则${a%.*}扩展为1.2.3

Job done.

任务完成。

The man page content for this is as follows (at least on my machine, YMMV):

手册页内容如下(至少在我的机器上,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.

感谢@x4d 提供的详细答案。仍然认为人们应该 RTFM。如果他们不理解手册,则发布另一个问题。

回答by aks

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

bash题为“男人节页变量替换”描述了使用${var#pattern}${var##pattern}${var%pattern},和${var%%pattern}

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

假设您有一个名为 的变量filename,例如,

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 $ver
1.2.3
% echo $ext
zip

回答by anubhava

Using Bash RegEx feature:

使用 Bash RegEx 功能:

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

回答by James

I think you can do this:

我认为你可以这样做:

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

substring=${string:0:4}

The last step removes the last 4 characters from the string. There's some more info on here.

最后一步从字符串中删除最后 4 个字符。有一些更多的信息在这里