简体   繁体   English

如何在bash中使用全局数组?

[英]How to use global arrays in bash?

I was searching through SO and google for a solution to my problem for 2 days but I had no luck. 我在SO和google中搜索了2天的解决方案,但是我没有运气。 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. 我的问题是我有一个数组,并用0初始化了它的元素,并且在for \\ while循环范围内修改了它的元素值。 But when I print the array's values outside the loop, I find it all 0's as their initial values!! 但是当我在循环外打印数组的值时,我发现所有的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 echo inside the if statement, it prints the correct value: 请注意,当我将echo放入if语句中时,它将输出正确的值:

if [ ${lengths[$j]} -le ${#element} ]
then lengths[$j]=${#element}
     echo ${lengths[$j]}
fi

What is wrong I'm doing? 我在做什么错? Am I missing something? 我想念什么吗?

The | while read element; do ... done | while read element; do ... done | while read element; do ... done | while read element; do ... done is running in a sub-shell, so its updates to the global are lost when the sub-shell exits. | while read element; do ... done在子外壳| while read element; do ... done中运行,因此在子外壳程序退出时,其对全局的更新会丢失。

One solution is to use bash's 'process substitution' to get the input to the while loop to run in a subshell instead. 一种解决方案是使用bash的“进程替换”来获取while循环的输入,以使其在子shell中运行。 See: Reading multiple lines in bash without spawning a new subshell? 请参阅: 在bash中读取多行而不产生新的subshel​​l?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM