Linux 在shell中,用点作为分隔符分割字符串的一部分

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19915452/
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-08-07 01:18:46  来源:igfitidea点击:

In shell, split a portion of a string with dot as delimiter

linuxshell

提问by rodee

I am new to shell scripting, can you please help with below requirement, thanks.

我是 shell 脚本的新手,请您帮忙解决以下要求,谢谢。

$AU_NAME=AU_MSM3-3.7-00.01.02.03
#separate the string after last "-", with "." as delimiter
#that is, separate "00.01.02.03" and print/save as below.
major=00
minor=01
micro=02
build=03

采纳答案by Mark Reed

First, note that you don't use $when assigning to a parameter in the shell. Your first line should be just this:

首先,请注意$在 shell 中分配参数时不要使用。你的第一行应该是这样的:

AU_NAME=AU_MSM3-3.7-00.01.02.03

Once you have that, then you can do something like this:

一旦你有了它,那么你可以做这样的事情:

IFS=. read major minor micro build <<EOF
${AU_NAME##*-}
EOF

where the ##*-strips off everything from the beginning of the string through the last '-', leaving just "00.01.02.03", and the IFS (Internal Field Separator) variable tells the shell where to break the string into fields.

其中##*-从字符串的开头到最后一个 '-' 去掉所有内容,只留下“00.01.02.03”,并且 IFS(内部字段分隔符)变量告诉 shell 在何处将字符串分解为字段。

In bash, zsh, and ksh93+, you can get that onto one line by shortening the here-document to a here-string:

在 bash、zsh 和 ksh93+ 中,您可以通过将 here-document 缩短为 here-string 来将其放到一行中:

IFS=. read major minor micro build <<<"${AU_NAME##*-}"

More generally, in those same shells (or any other shell that has arrays), you can split into an arbitrarily-sized array instead of distinct variables. This works in the given shells:

更一般地,在那些相同的 shell(或任何其他具有数组的 shell)中,您可以拆分为任意大小的数组而不是不同的变量。这适用于给定的外壳:

IFS=. components=(${AU_NAME##*-})

In older versions of ksh you can do this:

在旧版本的 ksh 中,您可以这样做:

IFS=. set -A components ${AU_NAME##*-}

That gets you this equivalence (except in zsh, which by default numbers the elements 1-4 instead of 0-3):

这让你得到这个等价(除了在 zsh 中,默认情况下元素编号为 1-4 而不是 0-3):

major=${components[0]}
minor=${components[1]}
micro=${components[2]}
build=${components[3]}

回答by paddy

In bash, you can do something like this:

在 中bash,您可以执行以下操作:

version=$(echo $AU_NAME | grep -o '[^-]*$')
major=$(echo $version | cut -d. -f1)
minor=$(echo $version | cut -d. -f2)
micro=$(echo $version | cut -d. -f3)
build=$(echo $version | cut -d. -f4)

The grepcall uses -owhich outputs only the matching part of the line. The match itself is every non-hyphen character to the end of the line.

grep调用使用-owhich 只输出该行的匹配部分。匹配本身是行尾的每个非连字符字符。

The cutcommand uses the delimeter .(-d.), and uses -fto select individual fields.

cut命令使用分隔符.( -d.),并用于-f选择单个字段。

It's a little clunky. I'm sure there are probably better ways to achieve this, but you can do quite a lot with grepand cutalone so they're handy tools to have in your arsenal.

它有点笨重。我敢肯定,有可能是更好的方式来实现这一点,但你可以做了很多与grepcut单独所以他们得心应手的工具到您的阿森纳。

回答by choroba

You can use parameter expansion and the special IFS variable.

您可以使用参数扩展和特殊的 IFS 变量。

#! /bin/bash
AU_NAME=AU_MSM3-3.7-00.01.02.03
IFS=. VER=(${AU_NAME##*-})
for i in {0..3} ; do
    echo ${VER[i]}
done

major=${VER[0]}
minor=${VER[1]}
micro=${VER[2]}
build=${VER[3]}

BTW, in an assignment, do not start the variable on the left hand side with a dollar sign.

顺便说一句,在赋值中,不要以美元符号开始左侧的变量。