循环中的多个管道,将管道结果保存到数组

循环中的多个管道,将管道结果保存到数组

我正在尝试执行以下操作(使用 bash): 搜索始终具有相同名称的文件并从这些文件中提取数据。我想将提取的数据存储在新数组中,我想我已经快到了,请参见下面的代码。

我正在搜索的文件都具有以下格式:

 #!/bin/bash
  echo "the concentration of NDPH is 2 mM, which corresponds to 2 molecules in a box of size 12 nm (12 x 12 x 12 nm^3)" > README_test

#find all the README* files and save the paths into an array called files
  files=()
  data1=()
  data2=()
  data3=()

  while IFS=  read -r -d $'\0'; do
files+=("$REPLY")
  #open all the files and extract data from them
  while read -r line
  do
name="$line"
echo "$name" | tr ' ' '\n'|  awk 'f{print;f=0;exit} /of/{f=1}' 
echo "$name" 
echo "$name" | tr ' ' '\n'|  awk 'f{print;f=0;exit} /of/{f=1}'
data1+=( "$echo "$name" | tr ' ' '\n'|  awk 'f{print;f=0;exit} /of/{f=1}' )" )    

# variables are not preserved...
# data2+= echo "$name"  | tr ' ' '\n'|  awk 'f{print;f=0;exit} /is/{f=1}'
echo "$name"  | tr ' ' '\n'|  awk 'f{print;f=0;exit} /size/{f=1}'
# variables are not preserved... 
# data3+= echo "$name"  | tr ' ' '\n'|  awk 'f{print;f=0;exit} /size/{f=1}'
  done < "$REPLY"
  done < <(find . -name "README*" -print0)
  echo ${data1[0]}

问题是,为我提供我想要的文件的确切输出的管道在循环中“不起作用”(不保留变量)。我不知道如何/是否可以使用进程替换来获得我想要的:一个充满管道输出的数组(data1、data2、data3)。

更新:所以我没有正确地将东西分配给数组(参见data1,它现在正在正确分配某物。)但是为什么

echo ${data1[0]}

echo "$name" | tr ' ' '\n'|  awk 'f{print;f=0;exit} /of/{f=1}'

不一样?

解决方案(根据 ilkkachu 接受的答案):

  #!/bin/bash
  echo "the concentration of NDPH is 2 mM, which corresponds to 2 molecules in a box of size 12 nm (12 x 12 x 12 nm^3)" > README_test
  files=()
  data1=()
  data2=()
  data3=()

  get_some_field() {    
 echo "$1" | tr ' ' '\n'|  awk -vkey="$2" 'f{print;f=0;exit} $0 ~ key {f=1}' 
  }

  #find all the README* files and save the paths into an array called files
  while IFS=  read -r -d $'\0'; do
files+=("$REPLY")
  #open all the files and extract data from them
  while read -r line
  do
name="$line"
echo "$name" 
echo "$name" | tr ' ' '\n'|  awk 'f{print;f=0;exit} /of/{f=1}'
data1+=( "$(get_some_field "$name" of)" )
data2+=( "$(get_some_field "$name" is)" )
data3+=( "$(get_some_field "$name" size)" )

  done < "$REPLY"
 done < <(find . -name "README*" -print0)

  echo ${data1[0]}
  echo ${data2[0]}
  echo ${data3[0]}

答案1

我假设您希望将输出echo ... | awk存储在变量中,特别是附加到其中一个数组。

首先,要捕获命令的输出,请使用"$( cmd... )"(命令替换)。作为一个简单的示例,这将打印您的主机名:

var=$(uname -n)
echo $var

其次,要追加到数组,您需要使用数组赋值语法,并在右侧加上括号。这会将 的值附加var到数组中:

array+=( $var )

第三, 的扩展$var和命令替换$(...)会受到分词的影响,因此您需要在它们周围使用括号。又是一个简单的例子,这将完整的输出uname -a作为单身的数组中的元素:

array+=( "$(uname -a)" )

或者,就您而言,完整:

data1+=( "$(echo "$1" | tr ' ' '\n'|  awk 'f{print;f=0;exit} /of/{f=1}')" )

(请注意,命令替换中的引号与命令替换中的引号不同外部它。之前的引用$1不会停止从 external 开始的引用$(),这与 SE 上的语法高亮似乎暗示的不同。)

您可以通过将管道放入函数中来使其更易于阅读:

get_data1() {
    echo "$name" | tr ' ' '\n'|  awk 'f{print;f=0;exit} /of/{f=1}'
}
...
data1+=( "$(get_data1)" )

或者,由于管道看起来相似,请使用该函数来避免重复代码:

get_some_field() {
    echo "$1" | tr ' ' '\n'|  awk -vkey="$2" 'f{print;f=0;exit} $0 ~ key {f=1}'
}

进而

data1+=( "$(get_some_field "$name" of)" )
data2+=( "$(get_some_field "$name" is)" )
data3+=( "$(get_some_field "$name" size)" )

(如果我没看错你的管道,也就是说,我没有测试上面的内容。)

相关内容