Bash
循環中的多個管道,將管道結果保存到數組
我正在嘗試執行以下操作(使用 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]}
我假設您希望將輸出
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
不會停止在外部開始的引用$()
,這與 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)" )
(如果我正確閱讀了您的管道,也就是說,我沒有測試上述內容。)