Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
518 views
in Technique[技术] by (71.8m points)

linux - Unable to add element to array in bash

I have the following problem. Let′s assume that $@ contains only valid files. Variable file contains the name of the current file (the file I'm currently "on"). Then variable element contains data in the format file:function.

Now, when variable element is not empty, it should be put into the array. And that's the problem. If I echo element, it contains exactly what I want, although it is not stored in array, so for cycle doesn't print out anything.

I have written two ways I try to insert element into array, but neither works. Can you tell me, What am I doing wrong, please?

I'm using Linux Mint 16.

#!/bin/bash

nm $@ | while read line
do
  pattern="`echo "$line" | sed -n "s/^(.*):$/1/p"`"
  if [ -n "$pattern" ]; then
    file="$pattern"  
  fi
  element="`echo "$line" | sed -n "s/^U ([0-9a-zA-Z_]*).*/$file:1/p"`"
  if [ -n "$element" ]; then
    array+=("$element")
    #array[$[${#array[@]}+1]]="$element"
    echo element - "$element"
  fi
done

for j in "${array[@]}"
do
  echo "$j"
done
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your problem is that the while loop runs in a subshell because it is the second command in a pipeline, so any changes made in that loop are not available after the loop exits.

You have a few options. I often use { and } for command grouping:

nm "$@" |
{
while read line
do
    …
done
for j in "${array[@]}"
do
    echo "$j"
done
}

In bash, you can also use process substitution:

while read line
do
    …
done < <(nm "$@")

Also, it is better to use $(…) in place of back-quotes `…` (and not just because it is hard work getting back quotes into markdown text!).

Your line:

element="`echo "$line" | sed -n "s/^U ([0-9a-zA-Z_]*).*/$file:1/p"`"

could be written:

element="$(echo "$line" | sed -n "s/^U ([0-9a-zA-Z_]*).*/$file:1/p")"

or even:

element=$(echo "$line" | sed -n "s/^U ([0-9a-zA-Z_]*).*/$file:1/p")

It really helps when you need them nested. For example, to list the lib directory adjacent to where gcc is found:

ls -l $(dirname $(dirname $(which gcc)))/lib

vs

ls -l `dirname `dirname \`which gcc\```/lib

I know which I find easier!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...