如何在 bash 中使用全局数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7758162/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use global arrays in bash?
提问by Eng.Fouad
I was searching through SO and google for a solution to my problem for 2 days but I had no luck. My problem is that I have an array and I initiate its elements with 0's, and I modify its elements' values inside for\while loop scope. But when I print the array's values outside the loop, I find it all 0's as their initial values!!
我在 SO 和 google 中搜索了 2 天的问题的解决方案,但我没有运气。我的问题是我有一个数组,我用 0 初始化它的元素,然后在 for\while 循环范围内修改它的元素值。但是当我在循环外打印数组的值时,我发现它们的初始值都是 0 !!
Here is my code:
这是我的代码:
#!/bin/bash
#
# This is a script to reformat CSV files into pretty-formatted txt files.
clear
echo 'This is a script to reformat CSV files into pretty-formatted txt files.'
echo
# Get number of elements.
elements=$(cat CSV_File | sed -n 1'p' | tr ',' '\n' | wc -l)
# "cat CSV_File" for getting text of the file.
# "sed -n 1'p'" for getting only first line.
# "tr ',' '\n'" for replacing ',' with '\n'.
# "wc -l" for getting number of lines (i.e number of elements).
# Get number of lines.
lines=$(cat CSV_File | wc -l)
# "cat CSV_File" for getting text of the file.
# "wc -l" for getting number of lines.
# Initiate an array for elements' lengths.
for ((i=1; $i < (( $elements + 1 )) ;i++))
do lengths[$i]="0"
done
# Find tallest element of each column and put the values into 'lengths' array.
for ((i=1; $i <= $lines ;i++))
do
j="1"
cat CSV_File | sed -n ${i}'p' | tr ',' '\n' | while read element
do
if [ ${lengths[$j]} -le ${#element} ]
then lengths[$j]=${#element}
fi
(( j++ ))
done
done
echo ${lengths[1]} # It should print 5 not 0
echo ${lengths[2]} # It should print 4 not 0
echo ${lengths[3]} # It should print 19 not 0
echo ${lengths[4]} # It should print 11 not 0
echo ${lengths[5]} # It should print 2 not 0
echo ${lengths[6]} # It should print 5 not 0
echo ${lengths[7]} # It should print 14 not 0
echo
...
and here is CSV_File contents:
这是 CSV_File 内容:
Jones,Bill,235 S. Williams St.,Denver,CO,80221,(303) 244-7989
Smith,Tom,404 Polk Ave.,Los Angeles,CA,90003,(213) 879-5612
Note that when I put echoinside the if statement, it prints the correct value:
请注意,当我放入echoif 语句时,它会打印正确的值:
if [ ${lengths[$j]} -le ${#element} ]
then lengths[$j]=${#element}
echo ${lengths[$j]}
fi
What is wrong I'm doing? Am I missing something?
我做错了什么?我错过了什么吗?
回答by P.T.
The | while read element; do ... doneis running in a sub-shell, so its updates to the global are lost when the sub-shell exits.
将| while read element; do ... done在一个子shell中运行,所以其对全球更新都将丢失的子shell退出时。
One solution is to use bash's 'process substitution' to get the input to the while loop to run in a subshell instead. See: Reading multiple lines in bash without spawning a new subshell?
一种解决方案是使用 bash 的“进程替换”来获取 while 循环的输入以在子 shell 中运行。请参阅: 在 bash 中读取多行而不产生新的子shell?

