Bash-将文件解析为数组

时间:2012-12-01 10:31:18

标签: linux arrays bash fileparsing

我有这个文件

Seq1
10 1 5
10 2 6
10 3 9
Seq2
15 2 7
15 4 9
15 8 12

我希望每个Seqs(Seq1,Seq2)都有这样的数组:

2ndColumn=(1,2,3) 
3rdColumn=(5,6,9)

我写了这个,但它没有打破while循环..

#!/bin/bash
2ndColumn=()
3rdColumn=()
while read line 
do
if [[ $line == S* ]] 
 echo "$line"
else
 i=0
 while [[ $line != S* ]]
 do
  2ndColumn[i]="$(echo $line | cut -d\  -f2)"
  3rdColumn[i]="$(echo $line | cut -d\  -f3)"
  i=$((i+1))
  read line
 done
 echo "${2ndColumn[@]} and ${3rdColumn[@]}"
fi
done < file
exit 0

这个脚本将永远迭代,它不会退出while循环。请帮助这个愚蠢的人类:(

3 个答案:

答案 0 :(得分:1)

我会重构它以使用单个循环而不是嵌套循环,并在stdin上嵌套读取调用:

2ndColumn=()
3rdColumn=()
i=0
while read line 
do
    if [[ $line == S* ]] 
        echo "$line ==> ${2ndColumn[@]} and ${3rdColumn[@]}"
        # reset the lists...
        2ndColumn=()
        3rdColumn=()
        i=0
    else
        2ndColumn[i]="$(echo $line | cut -d\  -f2)"
        3rdColumn[i]="$(echo $line | cut -d\  -f3)"
        i=$((i+1))
    fi
done

这将避免内部读取调用的问题,这可能在提供stdin文件句柄时被阻止。

答案 1 :(得分:1)

  • 您无法更改while read
  • 光标

我用一点为你写了这个,为数组名称添加seq N+1前缀:

#!/bin/bash

file=file.txt

while read line; do
    if [[ $line == S* ]]; then
        echo "$line"
        i=0
        ((Seq++))
    else
        declare seq${Seq}_2ndColumn[i]="$(echo $line | cut -d\  -f2)"
        declare seq${Seq}_3rdColumn[i]="$(echo $line | cut -d\  -f3)"
        ((i++))
    fi
done < "$file"

echo "${!seq*} arrays are declared"

<强>输出

seq1_2ndColumn seq1_3rdColumn seq2_2ndColumn seq2_3rdColumn arrays are declared

<强>说明

  • ${!pattern*}是bash的一个很好的功能,用于显示以 pattern 开头的变量
  • (( ))是一个算术命令,如果表达式非零,则返回退出状态0;如果表达式为零,则返回1。如果需要副作用(赋值),也用作“let”的同义词。请参阅http://mywiki.wooledge.org/ArithmeticExpression

<强>奖金

如果您可以控制数组中的内容,请尝试在结尾处执行此操作::

for s in ${!seq*}; do
    printf '\t%s\n' $(eval echo \${$s[@]})
done

请参阅http://mywiki.wooledge.org/BashFAQ/048

输出

seq1_2ndColumn
        1
        2
        3
seq1_3rdColumn
        5
        6
        9
seq2_2ndColumn
        2
        4
        8
seq2_3rdColumn
        7
        9
        12

答案 2 :(得分:0)

file=/PATH/TO/file.txt

arr1=( $(awk '/^Seq/{l++} l==1{print $2}' "$file") )
arr2=( $(awk '/^Seq/{l++} l==1{print $3}' "$file") )

echo "arr1:"
printf '\t%s\n' ${arr1[@]}

echo "arr2:"
printf '\t%s\n' ${arr2[@]}