bash的麻烦在循环分配到数组索引 [英] bash trouble assigning to an array index in a loop

查看:134
本文介绍了bash的麻烦在循环分配到数组索引的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我能得到这个在ksh中而不是在bash这实在是我发疯工作。
希望这是显而易见的事是我俯瞰。

I can get this to work in ksh but not in bash which is really driving me nuts. Hopefully it is something obvious that I'm overlooking.

我需要运行在输出的每一行都会存放在数组索引一个外部命令。

I need to run an external command where each line of the output will be stored at an array index.

这简单的例子看起来是设置在阵列中的循环然而正确的循环完成这些数组赋值都走了之后?就好像循环完全视为外部的壳呢?

This simplified example looks like it is setting the array in the loop correctly however after the loop has completed those array assignments are gone? It's as though the loop is treated completely as an external shell?

junk.txt

this is a
test to see
if this works ok

testa.sh

testa.sh

#!/bin/bash

declare -i i=0
declare -a array

echo "Simple Test:"
array[0]="hello"
echo "array[0] = ${array[0]}"

echo -e "\nLoop through junk.txt:"
cat junk.txt | while read line
do
    array[i]="$line"
    echo "array[$i] = ${array[i]}"
    let i++
done

echo -e "\nResults:"
echo "       array[0] = ${array[0]}"
echo " Total in array = ${#array[*]}"
echo "The whole array:"
echo ${array[@]}

输出

Simple Test:
array[0] = hello

Loop through junk.txt:
array[0] = this is a
array[1] = test to see
array[2] = if this works ok

Results:
      array[0] = hello
Total in array = 1
The whole array:
hello

因此​​,尽管在循环中,我们分配阵列[i]和所述回声进行验证。
但在循环后,我回到了阵[0]含你好,没有其他元素。

So while in the loop, we assign array[i] and the echo verifies it. But after the loop I'm back at array[0] containing "hello" with no other elements.

对面的bash 3,4和不同的平台相同的结果。

Same results across bash 3, 4 and different platforms.

推荐答案

由于while循环是一个管道,在循环体中所有变量赋值是局部的在其中执行循环子shell。 (我相信 KSH 在子shell不运行的命令,这就是为什么你有问题庆典)。做到这一点,而不是:

Because your while loop is in a pipeline, all variable assignments in the loop body are local to the subshell in which the loop is executed. (I believe ksh does not run the command in a subshell, which is why you have the problem in bash.) Do this instead:

while read line
do
    array[i]="$line"
    echo "array[$i] = ${array[i]}"
    let i++
done < junk.txt

很少,如果有的话,你想用来管一的的文件给另一个命令;使用输入重定向来代替。

Rarely, if ever, do you want to use cat to pipe a single file to another command; use input redirection instead.

更新:因为你需要从命令,而不是一个文件,另一个选项(如果可用)上运行的进程替换:

UPDATE: since you need to run from a command and not a file, another option (if available) is process substitution:

while read line; do
...
done < <( command args ... )

如果进程替换不可用,则需要输出到一个临时文件,并从该文件重定向输入。

If process substitution is not available, you'll need to output to a temporary file and redirect input from that file.

如果你正在使用bash 4.2或更高版本,您可以在循环之前执行这两个命令,和原来的管道进入的非循环将工作,因为while循环是的最后的命令酝酿中。

If you are using bash 4.2 or later, you can execute these two commands before your loop, and the original pipe-into-the-loop will work, since the while loop is the last command in the pipeline.

set +m    # Turn off job control; it's probably already off in a non-interactive script
shopt -s lastpipe
cat junk.txt | while read line; do ...; done

更新2:这是基于user1596414的评论环路少的解决方案

UPDATE 2: Here is a loop-less solution based on user1596414's comment

array[0]=hello
IFS=$'\n' array+=( $(command) )

的命令的输出被分成仅仅基于词语上换行符(使得每一行是一个单独的字),并添加所得线每次缝隙阵列到原来。如果你只使用循环建立数组这是非常好的。它也可能可以进行修改,以适应少量的每行处理,隐约类似于Python列表COM prehension。

The output of your command is split into words based solely on newlines (so that each line is a separate word), and appends the resulting line-per-slot array to the original. This is very nice if you are only using the loop to build the array. It can also probably be modified to accomodate a small amount of per-line processing, vaguely similar to a Python list comprehension.

这篇关于bash的麻烦在循环分配到数组索引的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆