2016-09-22 58 views
0

我有一个非常简单的sh脚本,我在这里制作系统cat调用,收集结果并解析一些相关信息,然后将信息存储在array中,这似乎工作得很好。但是,只要我退出存储信息的for循环,array似乎就清楚了。我想知道是否在for循环之外错误地访问array。我的脚本的相关部分:Shell Array清除原因不明

#!/bin/sh 

    declare -a QSPI_ARRAY=() 

    cat /proc/mtd | while read mtd_instance 
    do 
     # split result into individiual words 
     words=($mtd_instance) 
     for word in "${words[@]}" 
     do 
      # check for uboot 
      if [[ $word == *"uboot"* ]] 
      then 
       mtd_num=${words[0]} 
       index=${mtd_num//[!0-9]/} # strip everything except the integers 
       QSPI_ARRAY[$index]="uboot" 
       echo "QSPI_ARRAY[] at index $index: ${QSPI_ARRAY[$index]}" 

      elif [[ $word == *"fpga_a"* ]] 
      then 
       echo "found it: "$word"" 
       mtd_num=${words[0]} 
       index=${mtd_num//[!0-9]/} # strip everything except the integers 
       QSPI_ARRAY[$index]="fpga_a" 
       echo "QSPI_ARRAY[] at index $index: ${QSPI_ARRAY[$index]}" 

      # other items are added to the array, all successfully 

      fi 
     done 
     echo "length of array: ${#QSPI_ARRAY[@]}" 
     echo "----------------------" 
    done 

我的输出很好,直到我退出for循环。在for循环中,array大小会增加,我可以检查该项目是否已添加。在for循环结束后我检查array像这样:

echo "RESULTING ARRAY:" 
    echo "length of array: ${#QSPI_ARRAY[@]}" 
    for qspi in "${QSPI_ARRAY}" 
    do 
     echo "qspi instance: $qspi" 
    done 

这里是我的结果,echo d我显示:

dev: size erasesize name 

    length of array: 0 
    ------------- 
    mtd0: 00100000 00001000 "qspi-fsbl-uboot" 

    QSPI_ARRAY[] at index 0: uboot 

    length of array: 1 
    ------------- 
    mtd1: 00500000 00001000 "qspi-fpga_a" 

    QSPI_ARRAY[] at index 1: fpga_a 

    length of array: 2 
    ------------- 

    RESULTING ARRAY: 
    length of array: 0 
    qspi instance: 

编辑:一些调试之后,似乎我有莫名其妙地在这里两个不同的array。我初始化了array,如下所示:QSPI_ARRAY=("a" "b" "c" "d" "e" "f" "g"),然后在for循环中解析array后,它仍然是a,b,c等。我怎么在这里有两个不同的arrays

+2

你的家当,如果它完全被使用,需要是'#!/ bin/bash'。 '/ bin/sh'不支持数组。 – chepner

回答

1

这种结构:

cat /proc/mtd | while read mtd_instance 
do 
... 
done 

意味着,无论dodone之间来不能有shell环境是内部的任何影响仍然有done之后。

while循环位于管道的右侧(|)表示它在子外壳中运行。一旦循环结束,subshel​​l也一样。和它的所有可变设置。

如果你想要一个while循环,使周围的变化,不要使用管道。输入重定向不会创建一个子shell,在这种情况下,你可以直接从文件中读取:

while read mtd_instance 
do 
... 
done </proc/mtd 

如果你有一个更复杂的命令比cat,您可能需要使用进程替换。仍然使用cat作为一个例子,看起来像这样:

while read mtd_instance 
do 
... 
done < <(cat /proc/mtd) 

在你的示例代码的特定情况下,我认为你可以有所简化,或许是这样的:

#!/usr/bin/env bash  
QSPI_ARRAY=() 
while read -a words; do␣ 
    declare -i mtd_num=${words[0]//[!0-9]/} 
    for word in "${words[@]}"; do 
    for type in uboot fpga_a; do 
     if [[ $word == *$type* ]]; then 
     QSPI_ARRAY[mtd_num]=$type 
     break 2 
     fi 
    done 
    done 
done </proc/mtd