bash脚本 - 为什么在函数下设置值而不在函数外部设置

时间:2014-07-23 12:24:38

标签: linux bash function

以下bash脚本的目标是读取CSV文件(all_words.CSV)并打印参数和值,但我有一个非常奇怪的问题。

当我运行脚本时,所有单词参数(word1-word8)都被打印 - 直到现在每件事情都很好!当我想在函数外打印word1=$word1时,出于某种原因,word1 {{1 }}?

为什么所有参数(not get the value)都在函数中打印值,当我想在函数外打印word1-word8时,word1没有值?

我尝试使用export命令,但它没有帮助; word1

请告知它是怎么回事?这有什么问题?

export word1=$word1

 #!/bin/bash

 read_csv ()
  {
  CSV_LINE=2

 vars=()
 c=1
 while IFS=, read -ra arr; do
    if ((c==1)); then
      vars+=("${arr[@]}")
   elif ((c==CSV_LINE)); then
     for ((i=0; i<${#arr[@]}; i++)); do
        declare ${vars[$i]}="${arr[$i]}"
     done
  fi
   ((c++))
  done <  all_words.CSV 

 echo CSV_LINE=$CSV_LINE
 echo word1=$word1
 echo word2=$word2
 echo word3=$word3
 echo word4=$word4
 echo word5=$word5
 echo word6=$word6
 echo word7=$word7
 echo word8=$word8

  }


read_csv

echo word1=$word1

脚本输出示例:

 more all_words.CSV

  word1,word2,word3,word4,word5,word6,word7,word8
  &^#G TR /erfernfjer *&^NHY " "" ? /  $@H,@Y^%" E "R$%*&*UJ,**U&^#%%@$^&//  \\,^T%!#&^YG.+___KI*&HHTY,%%@$#!%^#&,P/\06E87*UHG11#
 ,edehu234#@!&,~hum&T%6e4

3 个答案:

答案 0 :(得分:5)

man bashdeclare下解释:

  

在函数中使用时,declare使NAME成为本地的,与local命令一样。

答案 1 :(得分:3)

    declare -g ${vars[$i]}="${arr[$i]}"
#           ^^

使用declare -g在函数中声明全局级别的变量。来自man bash

   declare [-aAfFgilrtux] [-p] [name[=value] ...]
          [...]  The -g option forces
          variables  to  be  created or modified at the global scope, even
          when declare is executed in a shell function.  It is ignored  in
          all  other cases. [...]

以下是-g标志的简单演示(在GNU bash版本4.2.37上按预期工作):

#!/bin/bash

function f() {
    declare -g V
    V="hello"
}

f
echo $V

答案 2 :(得分:2)

  

请建议......

更好地使用printf

printf -v "${vars[$i]}" "%s" "${arr[$i]}"

虽然我建议使用关联数组。这是更合适的解决方案:

#!/bin/bash

declare -A CSV_VALUES
declare -a CSV_KEYS

function read_csv {
    CSV_VALUES=() CSV_KEYS=()

    local VALUES I

    {
        IFS=, read -ra CSV_KEYS
        IFS=, read -ra VALUES
    } < all_words.csv

    for I in "${!CSV_KEYS[@]}"; do
        CSV_VALUES[${CSV_KEYS[I]}]=${VALUES[I]}
    done
}

read_csv  ## Perhaps pass the filename to read_csv as an argument instead?

# We can do for KEY in "${!CVS_VALUES[@]}" but the order is uncertain.

for KEY in "${CSV_KEYS[@]}"; do
    echo "CSV_VALUES[$KEY]=${CSV_VALUES[$KEY]}"
done