首页 > 解决方案 > 将字符串分配给数组而不是在 bash 脚本中使用 read?

问题描述

在 bash 脚本中,我想将包含以“:”分隔的变量的字符串转换为数组。

我看到建议的方法通常是

IFS=: read -r -a myarray <<< "$mystring"

我改用了一个对我来说看起来更简单的命令:

IFS=: myarray=($mystring)

此外,在我的电脑上它可以工作。请参阅下面的脚本

#!/bin/bash

mystring="var01:var02:var03:var04"

IFS=: myarray=($mystring)

echo "first variable is" "${myarray[0]}"
echo "second variable is" "${myarray[1]}"
echo "..."

输出是

first variable is var01
second variable is var02
...

但是,由于我没有在网上找到这样的例子,我不确定它是否正确......

在 bash 脚本中使用它会有什么问题?是否符合标准?

谢谢你的建议。

标签: arraysbashparsing

解决方案


第一个问题很好。您提出的替代方案确实存在问题。首先考虑

$ str='a:%:*'
$ IFS=: read -r -a arr <<< "$str"
$ echo "${arr[@]}"
a % *

结果是预期的。因为"$str"在此处字符串中被引用,所以它不会进行文件名扩展(称为 globbing)并且一切正常。

另一方面...

$ str='a:%:*'
$ IFS=: arr=($str)
$ echo "${arr[@]}"
a % 07-13:37:38.png 07-13:37:49.png Documents Downloads Pictures Music Xresources

在第二种情况下,$str未加引号并进行文件名扩展,这意味着*扩展到我当前目录中的所有文件!唉!

这些形式都不符合 POSIX,因为 POSIX 没有在 shell 中定义数组。但是两者在 Bash 中都是完全有效的,尽管正如所证明的那样,它们做不同的事情。

Bash 手册中的参考:文件名扩展


正如您所指出的,您可以使用set -f来禁用文件名扩展。这将解决 的问题IFS=: arr=($str),但可能会让一些人感到惊讶。如果采用这种方式,请在该行之后立即将其设置回来,set +f否则该设置将应用于脚本的整个其余部分。它增加了解决方案的复杂性,因此我建议尽可能避免这种情况。


推荐阅读