我正在尝试执行以下操作(使用 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)" )
(如果我没看错你的管道,也就是说,我没有测试上面的内容。)