shell脚本数组不会从for循环中填充

时间:2014-11-15 12:42:16

标签: arrays shell

任何人都可以告诉我为什么要创建数组: cccr [$ string_1] = $ string_2 #不工作?

#!/bin/bash

firstline='[Event "Marchand Open"][Site "Rochester NY"][Date "2005.03.19"][Round "1"][White "Smith, Igor"][Black "Jones, Matt"][Result "1-0"][ECO "C01"][WhiteElo "2409"][BlackElo "1911"]'

unset cccr
declare -A cccr

(IFS='['; for word in $firstline; do

string_1=$(echo $word | cut -f1 -d'"' | tr -d ' ')
string_2=$( echo $word | cut -f2 -d'"' )

if [ ! -z $string_1 ]; then # If $string_1 is not empty
cccr[$string_1]=$string_2 # why doesn't this line work?
fi

done)

echo  ${cccr[Event]} # echos null string

1 个答案:

答案 0 :(得分:2)

发生这种情况是因为string_1的值在第一次迭代时为空。

示例:

#!/bin/bash

firstline='[Event "Marchand Open"][Site "Rochester NY"][Date "2005.03.19"][Round "1"][White "Smith, Igor"][Black "Jones, Matt"][Result "1-0"][ECO "C01"][WhiteElo "2409"][BlackElo "1911"]'

unset cccr
declare -A cccr

(IFS='['; for word in $firstline; do

string_1=$( echo $word | cut -f1 -d'"' )
string_2=$( echo $word | cut -f2 -d'"' )

echo "$string_1 - $string_2"
#cccr[$string_1]=$string_2

done)

输出:

 - # Problem !
Event  - Marchand Open
Site  - Rochester NY
...

您必须修改脚本以防止值为空。

一个非常简单的解决方法是在使用之前检查string_1的值。

示例:

# ...
string_1=$( echo $word | cut -f1 -d'"' )
string_2=$( echo $word | cut -f2 -d'"' )

if [ ! -z $string_1 ]; then # If $string_1 is not empty
    echo "$string_1 - $string_2"
    cccr[$string_1]=$string_2
fi
# ...

来自[

的手册页
-z STRING
              the length of STRING is zero

输出:

Event  - Marchand Open
Site  - Rochester NY
# ... No problem

修改

顺便说一句,如果查看string_1的值,您会看到值为Event' '而不是Event(事件结尾处有空格) 因此cccr[Event]不存在,但cccr[Event ]存在。 要解决此问题,您可以删除string_1中的空格:

string_1=$(echo $word | cut -f1 -d'"' | tr -d ' ') # tr -d ' ' deletes all the whitespaces

编辑2

我忘了告诉你,如果它不起作用,它是正常的。实际上,循环是在子shell环境中执行的。因此数组填充在子shell中,但不在当前shell中。 来自bash的手册页:

(list) list  is  executed in a subshell environment (see COMMAND EXECUTION ENVIRONMENT below).  Variable
              assignments and builtin commands that affect the shell's environment  do  not  remain  in  effect
              after the command completes.  The return status is the exit status of list.

所以 2个解决方案

1。不要在子shell中运行循环(删除括号)。

# ...
OLDIFS=$IFS
IFS='['
for word in $firstline; do
    string_1=$(echo $word | cut -f1 -d'"' | tr -d ' ')
    string_2=$(echo $word | cut -f2 -d'"')
    if [ ! -z $string_1 ]; then
        cccr[$string_1]=$string_2
    fi
done
IFS=$OLDIFS

echo "Event = ${cccr[Event]}"
echo "Site = ${cccr[Site]}"

输出:

Event = Marchand Open
Site = Rochester NY

2. 在子shell中使用您的数组。

# ...
(IFS='['
for word in $firstline; do
    string_1=$(echo $word | cut -f1 -d'"' | tr -d ' ')
    string_2=$(echo $word | cut -f2 -d'"')
    if [ ! -z $string_1 ]; then # If $string_1 is not empty
    cccr[$string_1]=$string_2
    fi
done
echo "Event = ${cccr[Event]}"
echo "Site = ${cccr[Site]}"
)

输出:

Event = Marchand Open
Site = Rochester NY