【问题标题】:Reading a text file to fill arrays in bash [duplicate]读取文本文件以填充 bash 中的数组 [重复]
【发布时间】:2018-08-07 14:56:15
【问题描述】:

我有一个输入文本文件,如下所示:

# string name           |       String type (x,y,or z)

name_1                  |               x
name_2                  |               y
name_3                  |               z

我要阅读并填写

  • 包含所有字符串名称的全局数组
  • 三个数组(比如 list_xlist_ylist_z),具体取决于字符串类型

这是我的脚本:

# Array initialization
list_global=();list_x=();list_y=();list_z=()
# Remove blank lines if there are some
sed -i '/^[[:space:]]*$/d' input_tab.txt
# Reading file
while read line
do
        name=$(echo $line |awk -F "|" '{print $1}'|sed 's/ //g')
        type=$(echo $line |awk -F "|" '{print $2}'|sed 's/ //g')
        # Checking data are correctly read
        printf "%6s is of type %2s \n" "$name" "$type"

        # Appending to arrays
        list_global+=("$name")

        if [ "$type"==x ]
        then
                list_x+=("$name")
        elif [ "$type"==y ]
        then
                list_y+=("$name")
        elif [ "$type"==z ]
        then
                list_z+=("$name")
        fi

done < input_tab.txt
# Print outcome
echo global_list ${list_global[@]}
echo -e "\n \n \n "

echo list_x ${list_x[@]}
echo list_y ${list_y[@]}
echo list_z ${list_z[@]}

这会产生以下输出

name_1 is of type  x
name_2 is of type  y
name_3 is of type  z
global_list name_1 name_2 name_3


list_x name_1 name_2 name_3
list_y
list_z

意味着我的输入文件被正确读取,并且我填充数组的方式是有效的。 我无法理解为什么它会系统地满足它通过的第一个“如果”。如果我首先测试 if [ "$type"==z ],那么一切都会转到 list_z。

注意事项:

  • 使用 switch/case 代替 if 会导致相同的结果
  • 我运行 bash 4.1.2

任何帮助/解释将不胜感激, 提前致谢

【问题讨论】:

  • 如果您在[ ] 中的==(或者,更便携的=)周围不留空格,则内容将被解释为单个字符串并始终评估为真。由于case 不包含这样的比较,我看不出您如何使用case 获得相同的结果。
  • 旁注:代替while read line 然后使用awk,您可以让Bash 拆分您的行:while read name _ type 为您删除空格。
  • 如果你有 Bash 4.3 或更新版本,你可以使用 namerefs 并简化为 while read name _ type; do declare -n list=list_$type; list+=("$name"); done

标签: bash list


【解决方案1】:

此代码将解决问题实际上是语法问题,我更改的是 if 条件而不是:

if [ "$type"==x ]

现在看起来像:

if [ "$type" == "x" ]

所以在您的情况下,使用您的语法,if 条件将始终评估为真,这就是为什么它将所有内容都提供给第一个列表。

# Array initialization
list_global=();list_x=();list_y=();list_z=()
# Remove blank lines if there are some
sed -i '/^[[:space:]]*$/d' remo.txt
# Reading file
while read line
do
        name=$(echo $line |awk -F "|" '{print $1}'|sed 's/ //g')
        type=$(echo $line |awk -F "|" '{print $2}'|sed 's/ //g')
        # Checking data are correctly read
        printf "%6s is of type %2s \n" "$name" "$type"

        # Appending to arrays
        list_global+=("$name")

        if [ "$type" == "x" ]
        then
                list_x+=("$name")

        elif [ "$type" == "y" ]
        then
                list_y+=("$name")

        elif [ "$type" == "z" ]
        then
                list_z+=("$name")
        fi

done < remo.txt
# Print outcome
echo global_list ${list_global[@]}
echo -e "\n \n \n "

echo list_x ${list_x[@]}
echo list_y ${list_y[@]}
echo list_z ${list_z[@]}

输出将是:

list_x name_1
list_y name_2
list_z name_3

【讨论】:

  • 是的,请检查一下
  • 谢谢,刷新没有显示任何内容。
  • declare -p list_x list_y list_z 是发出所有数组内容的更好方法。 echo ${list_x[@]} 无法显示list_x=( "foo bar" )list_x=( "foo" "bar" ) 之间的区别,也没有显示list_x=( '*' )(包含星号的单个字符串的列表)和list_x=( * )(包含星号的列表)之间的区别文件名)。另请参阅BashPitfalls #14
  • 除此之外,请参阅How to Answer 中的“回答好问题”部分,尤其是关于“...已经被问到并回答了很多问题的要点”之前的时间”。
  • 我想说这对我不起作用。我实际上发现sed 's/ //g' 是有问题的。我使用参数扩展来删除空白,它起作用了。目前尚不清楚为什么会这样做......尽管如此,答案指出了一个很好的观点,所以我会接受这个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-16
  • 1970-01-01
  • 2019-04-09
  • 2013-09-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多