我動態迭代一個 csv 檔案并選擇符合我需要的條件的列。我的 CSV 用逗號分隔。我將這些索引保存到一個看起來像的陣列中
echo "${cols_needed[@]}"
1 3 4 7 8
然后我需要將這些列寫入一個新檔案,并且我嘗試了以下 cut 和 awk 命令,但是,由于陣列是動態創建的,我似乎無法找到可以一次選擇它們的正確命令。我嘗試過剪切、awk 和粘貼命令。
awk -v fields=${cols_needed[@]} 'BEGIN{ n = split(fields,f) }
{ for (i=1; i<=n; i) printf "%s%s", $f[i], (i<n?OFS:ORS) }' test.csv
這會引發錯誤,因為它無法拆分欄位,除非我對它們進行硬編碼(即使如此,它也只能執行 2 個),在空格上拆分。
fields="1 2’
我曾嘗試動態創建 -f 引數,但只能在這樣的回圈中使用一個變數來執行此操作
for item in "${cols_needed[@]}";
do
cat test.csv | cut -f$item
done
一次輸出一列。
我試圖用逗號動態創建它 - 輸入為 1,3,4,7 ...
cat test.csv | cut -f${cols_needed[@]};
這也不起作用!
任何幫助表示贊賞!我知道 awk 不像 bash 那樣作業,我們不能以同樣的方式傳遞變數。我覺得我有點繞圈子了!提前致謝。
uj5u.com熱心網友回復:
你的第一種方法沒問題,只是:
- 更改
-v fields=${cols_needed[@]}為-v fields="${cols_needed[*]}", 以將陣列作為單個 shell 字傳遞 - 添加
FS=OFS=","到 BEGIN,拆分后(您要在空格上拆分,在 FS 更改為 之前,) - IE。
BEGIN {n = split(fields, f); FS=OFS=","}
此外,如果參考的 csv 欄位中沒有嵌入逗號,您可以使用cut:
IFS=,; cut -d, -f "${cols_needed[*]}" test.csv
如果被嵌入的逗號,你可以使用gawk的FPAT,只在不帶引號的逗號分割的欄位。
這是一個使用它的例子。
# prepend $ to each number
for i in "${cols_needed[@]}"; do
fields[j ]="\$$i"
done
IFS=,
gawk -v FPAT='([^,] )|(\"[^\"] \")' -v OFS=, "{print ${fields[*]}}"
將 shell 代碼注入 awk 命令通常不是很好的做法,但在這里 IMO 沒問題。
uj5u.com熱心網友回復:
擴展我的評論:將bash陣列傳遞到awk:
將陣列作為awk變數傳入:
$ cols_needed=(1 3 4 7 8)
$ typeset -p cols_needed
declare -a cols_needed=([0]="1" [1]="3" [2]="4" [3]="7" [4]="8")
$ awk -v fields="${cols_needed[*]}" 'BEGIN{n=split(fields,f); for (i=1;i<=n;i ) print i,f[i]}'
1 1
2 3
3 4
4 7
5 8
通過行程替換將陣列作為“檔案”傳入:
$ awk 'FNR==NR{f[ n]=$1;next} END {for (i=1;i<=n;i ) print i,f[i]}' <(printf "%s\n" "${cols_needed[@]}")
1 1
2 3
3 4
4 7
5 8
至于 OP 從 .csv 檔案中提取一組特定列的主要問題......
借用 dawg 的 .csv 檔案:
$ cat file.csv
1,2,3,4,5,6,7,8
11,12,13,14,15,16,17,18
21,22,23,24,25,26,27,28
擴展將bash陣列作為awk變數傳入的建議:
awk -v fields="${cols_needed[*]}" '
BEGIN { FS=OFS=","
n=split(fields,f," ")
}
{ pfx=""
for (i=1;i<=n;i ) {
printf "%s%s", pfx, $(f[i])
pfx=OFS
}
print ""
}
' file.csv
注意:這假設 OP 提供了有效的列號串列;如果對輸入(列)數字的有效性存在疑問,那么 OP 可以添加一些邏輯來解決上述疑問(例如,它們是整數嗎?它們是正整數嗎?它們是否參考了file.csv實際存在的欄位(in )?,等等)
這會產生:
1,3,4,7,8
11,13,14,17,18
21,23,24,27,28
uj5u.com熱心網友回復:
假設你在 bash 中有這個變數:
$ echo "${cols_needed[@]}"
3 4 7 8
這個 CSV 檔案:
$ cat file.csv
1,2,3,4,5,6,7,8
11,12,13,14,15,16,17,18
21,22,23,24,25,26,27,28
您可以通過這種方式在 awk 中選擇該 csv 檔案的列:
awk '
BEGIN{FS=OFS=","}
FNR==NR{split($0, cols," "); next}
{
s=""
for (e=1;e<=length(cols); e )
s=e<length(cols) ? s $(cols[e]) OFS : s $(cols[e])
print s
}' <(echo "${cols_needed[@]}") file.csv
印刷:
3,4,7,8
13,14,17,18
23,24,27,28
或者,您可以這樣做:
awk -v cw="${cols_needed[*]}" '
BEGIN{FS=OFS=","; split(cw, cols," ")}
{
s=""
for (e=1;e<=length(cols); e )
s=e<length(cols) ? s $(cols[e]) OFS : s $(cols[e])
print s
}' file.csv
# same output
順便說一句,你可以完全做到這一點cut:
cut -d ',' -f $(IFS=, ; echo "${cols_needed[*]}") file.csv
3,4,7,8
13,14,17,18
23,24,27,28
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/358774.html
