【问题标题】:how do I output the contents of a while read line loop to multiple arrays in bash?如何将 while 读取行循环的内容输出到 bash 中的多个数组?
【发布时间】:2011-09-19 17:45:02
【问题描述】:

我读取一个目录的文件并将每个文件名放入一个数组(搜索) 然后我使用循环遍历数组中的每个文件名(SEARCH),并使用 while read line 循环打开它们,并将每一行读入另一个数组(filecount)。我的问题是它有一个 39 行的巨大数组(每个文件有 13 行),我需要它是 3 个单独的数组,其中 filecount1[line1] 是第一个文件的第一行,依此类推。到目前为止,这是我的代码...

typeset -A files
for file in ${SEARCH[@]}; do
    while read line; do
        files["$file"]+="$line"
    done < "$file"
done

所以,感谢 Ivan 提供的这个示例!但是我不确定我是如何将它放入一个单独的数组中的,因为在这个例子中,所有的数组都不会被命名为“文件”吗?

【问题讨论】:

    标签: arrays bash for-loop while-loop


    【解决方案1】:

    如果您只是想将文件内容存储到数组中:

    declare -A contents
    for file in "${!SEARCH[@]}"; do
        contents["$file"]=$(< $file)
    done
    

    如果你想将单独的行存储在一个数组中,你可以创建一个伪多维数组:

    declare -A contents
    for file in "${!SEARCH[@]}"; do
        NR=1
        while read -r line; do
            contents["$file,$NR"]=$line
            (( NR++ ))
        done < "$file"
    done
    
    for key in "${!contents[@]}"; do 
        printf "%s\t%s\n" "$key" "${contents["$key"]}"
    done
    

    【讨论】:

    • Glenn,您的解决方案运行良好,但它仍然将 SEARCH[] 中包含的文件放入一个数组中,contents[] 我正在寻找的是一种结构,它将获取 SEARCH[] 中的每个文件,为该文件创建一个数组,然后将该文件的内容作为文件数组的元素。因此,如果我在SEARCH[] 中有 3 个文件,并且每个文件有 5 行,我希望能够拥有 3 个数组,每个数组有 5 个不同的元素......我相信 Ivan 正确地说了“动态创建数组”,但我仍然无法找出他的例子......:S
    • 如果你认为你真的需要这样做,你将不得不通过创建变量名和eval来跳过很多圈子。这样很容易造成无法维护的混乱。
    • 是的,你可能是对的,我正在尝试通过我的逻辑思考,看看我是否能以不同的方式做我想做的事。谢谢大家的帮助。
    【解决方案2】:

    第 6 行是

    $filecount[$linenum]}="$line" 
    

    似乎在$ 之后缺少{
    应该是:

    ${filecount[$linenum]}="$line" 
    

    如果上述情况属实,那么它尝试将输出作为命令运行
    第 6 行是(在上面“修复”它之后):

    ${filecount[$linenum]}="$line"
    

    但是${filecount[$linenum]} 是一个,您不能对一个值进行赋值
    应该是:

    filecount[$linenum]="$line"
    

    现在我很困惑,{ 是否真的丢失了,或者} 是实际的错字:S:P


    顺便说一句,bash 也支持这种语法

    filecount=$((filecount++)) # no need for $ inside ((..)) and use of increment operator ++
    

    这应该可行:

    typeset -A files
    for file in ${SEARCH[@]}; do       # foreach file 
        while read line; do            # read each line
            files["$file"]+="$line"    # and place it in a new array
        done < "$file"                 # reading each line from the current file
    done
    

    一个小测试表明它有效

    # set up
    mkdir -p /tmp/test && cd $_
    echo "abc" > a
    echo "foo" > b
    echo "bar" > c
    
    # read files into arrays
    typeset -A files
    for file in *; do 
        while read line; do
            files["$file"]+="$line" 
        done < "$file"
    done
    
    # print arrays
    for file in *; do
        echo ${files["$file"]}
    done
    
    # same as:
    echo ${files[a]}     # prints: abc
    echo ${files[b]}     # prints: foo
    echo ${files[c]}     # prints: bar
    

    【讨论】:

    • 我认为原来的} 是一个错字;)但是在你提出filecount[$linenum]="$line" 的建议之后,它起作用了!在将这么多行“写入”到 filecount 之后如何使 linenum 数组“重新启动”有什么想法吗?
    • 好的,现在我已经让循环正常工作了,我不确定如何使用特定的 linenum 访问 filecount 数组中的元素...?
    • @Ryan:linenum 不是数组,您在数组和非数组上下文中都使用文件计数。您应该将您的问题更正为当前版本的代码,将 filecount 的两种用途分开,然后澄清您所说的“重新启动”和“这么多行”的意思。但是,您当然可以取消定义数组并将 linenum 重置为 1 以删除当前数组内容。
    • @Ryan: echo ${filecount[$index]}
    • 如果我理解正确的话,Ryan 实际上是在尝试以动态方式创建数组。每个文件一个数组,每个数组都将保存文件的内容。这可以通过关联数组来完成。请参阅this page 了解更多信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-17
    • 2018-09-05
    • 2020-02-10
    • 2016-02-13
    • 2012-01-24
    • 2015-09-13
    相关资源
    最近更新 更多