无法在bash中向array添加元素

时间:2022-10-28 16:10:49

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.

我有以下问题。我们假设$ @只包含有效文件。变量文件包含当前文件的名称(我当前“打开”的文件)。然后变量元素包含格式文件: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.

我正在使用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

1 个解决方案

#1


11  

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.

您的问题是while循环在子shell中运行,因为它是管道中的第二个命令,因此在循环退出后,该循环中所做的任何更改都不可用。

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:

在bash中,您还可以使用进程替换:

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!).

另外,最好使用$(...)来代替后引号`...`(而不仅仅是因为将引号引回到markdown文本是一项艰苦的工作!)。

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:

当你需要它们嵌套时它真的很有用。例如,要列出与找到gcc的位置相邻的lib目录:

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

vs

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

I know which I find easier!

我知道哪个更容易找到!

#1


11  

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.

您的问题是while循环在子shell中运行,因为它是管道中的第二个命令,因此在循环退出后,该循环中所做的任何更改都不可用。

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:

在bash中,您还可以使用进程替换:

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!).

另外,最好使用$(...)来代替后引号`...`(而不仅仅是因为将引号引回到markdown文本是一项艰苦的工作!)。

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:

当你需要它们嵌套时它真的很有用。例如,要列出与找到gcc的位置相邻的lib目录:

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

vs

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

I know which I find easier!

我知道哪个更容易找到!