如何在bash shell中将一个字符串拆分为多个变量?

cru*_*nut 141 variables bash shell

我一直在寻找一个解决方案并找到类似的问题,只是他们试图在它们之间用空格分割句子,而答案对我的情况不起作用.

目前一个变量被设置为像这样的字符串:
ABCDE-123456
我想将它分成2个变量,同时消除" - ".即:
var1=ABCDE
var2=123456

怎么可能做到这一点?


这是对我有用的解决方案:
var1=$(echo $STR | cut -f1 -d-)
var2=$(echo $STR | cut -f2 -d-)

是否可以使用cut命令在没有分隔符的情况下工作(每个字符都设置为变量)?

var1=$(echo $STR | cut -f1 -d?)
var2=$(echo $STR | cut -f1 -d?)
var3=$(echo $STR | cut -f1 -d?)
etc.

Pau*_*ce. 178

read与这IFS是完美的:

$ IFS=- read var1 var2 <<< ABCDE-123456
$ echo "$var1"
ABCDE
$ echo "$var2"
123456
Run Code Online (Sandbox Code Playgroud)

编辑:

以下是如何将每个字符读入数组元素:

$ read -a foo <<<"$(echo "ABCDE-123456" | sed 's/./& /g')"
Run Code Online (Sandbox Code Playgroud)

转储数组:

$ declare -p foo
declare -a foo='([0]="A" [1]="B" [2]="C" [3]="D" [4]="E" [5]="-" [6]="1" [7]="2" [8]="3" [9]="4" [10]="5" [11]="6")'
Run Code Online (Sandbox Code Playgroud)

如果字符串中有空格:

$ IFS=$'\v' read -a foo <<<"$(echo "ABCDE 123456" | sed 's/./&\v/g')"
$ declare -p foo
declare -a foo='([0]="A" [1]="B" [2]="C" [3]="D" [4]="E" [5]=" " [6]="1" [7]="2" [8]="3" [9]="4" [10]="5" [11]="6")'
Run Code Online (Sandbox Code Playgroud)

  • 伟大的,优雅的bash唯一的方式,没有不必要的叉子. (4认同)
  • 此解决方案还有一个好处,如果分隔符不存在,`var2` 将为空 (2认同)

mkb*_*mkb 149

如果你知道它只是两个字段,你可以跳过额外的子进程,如下所示:

var1=${STR%-*}
var2=${STR#*-}
Run Code Online (Sandbox Code Playgroud)

这是做什么的?${STR%-*}删除$STR匹配-*从字符串末尾开始的模式的最短子字符串.${STR#*-}做同样的事情,但是从*-模式开始,从字符串的开头开始.他们每个都有对应物%%,##并找到最长的锚定模式匹配.如果有人有一个有用的助记符来记住哪个做了哪个,请告诉我!我总是要努力记住.

  • 助记符:"#"在标准键盘的"%"左侧,因此"#"删除前缀(在左侧),"%"删除后缀(在右侧). (12认同)
  • 加1了解您的POSIX外壳功能,避免昂贵的叉子和管道,以及缺乏基本原理. (8认同)
  • 另一个助记符,因为您的键盘可能不同(有些只是“感觉”布局,而不是知道它):%符号通常出现在数字*之后*,例如90%,因此它是一个后缀。# 符号通常是前导注释,甚至只是主题标签中的第一个字符,因此它是一个常见的前缀。两个修饰符的目的都是删除,一个只是删除前缀(#),另一个删除后缀(%)。 (4认同)
  • 不知道“没有 bashisms”,因为这已经相当神秘了……如果您的分隔符是换行符而不是连字符,那么它会变得更加神秘。另一方面,*它适用于换行符*,所以就是这样。 (3认同)
  • 我终于找到了它的文档:[Shell-Parameter-Expansion](https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion) (3认同)

Rob*_*b I 140

如果你的解决方案不一定是通用的,即只需要像你的例子一样工作,你可以这样做:

var1=$(echo $STR | cut -f1 -d-)
var2=$(echo $STR | cut -f2 -d-)
Run Code Online (Sandbox Code Playgroud)

我选择cut这里是因为你可以简单地扩展代码以获得更多变量......


tri*_*eee 42

听起来像是set一个习惯的工作IFS.

IFS=-
set $STR
var1=$1
var2=$2
Run Code Online (Sandbox Code Playgroud)

(你需要在一个带有函数的函数中执行此操作,local IFS这样你就不会弄乱脚本的其他部分,而这些部分需要IFS符合你的期望.)

  • 如果我们需要编写非Bash特定的东西,这是一个非常好的解决方案.要处理`IFS'问题,可以在覆盖它之前在开头添加`OLDIFS = $ IFS`,然后在`set`行之后添加`IFS = $ OLDIFS`. (3认同)
  • 也许在“set -- $STR”之前添加一个“set -f”以禁用路径名扩展,或者如果“$STR”包含模式,它将捕获路径文件名。 (3认同)

anu*_*ava 23

使用bash正则表达式功能:

re="^([^-]+)-(.*)$"
[[ "ABCDE-123456" =~ $re ]] && var1="${BASH_REMATCH[1]}" && var2="${BASH_REMATCH[2]}"
echo $var1
echo $var2
Run Code Online (Sandbox Code Playgroud)

OUTPUT

ABCDE
123456
Run Code Online (Sandbox Code Playgroud)

  • 喜欢预先定义“re”以供以后使用! (2认同)