[英]Most efficient method to split file into multiple files based on a column
我一直在尋找一種有效地實現這一目標的方法,並且無法提出最佳解決方案。
要求很簡單。 我有一個以下格式的文件。
$cat mymainfile
rec1,345,field3,....field20
rec1,645,field3,....field20
rec12,345,field3,....field20
frec23,45,field3,....field20
rec34,645,field3,....field20
在拆分操作結束時,我希望有多個具有這些名稱的單獨文件
$cat some_prefix_345_some_suffix_date
rec1,345,field3,....field20
rec12,345,field3,....field20
$cat some_prefix_645_some_suffix_date
rec1,645,field3,....field20
rec34,645,field3,....field20
$cat some_prefix_45_some_suffix_date
frec23,45,field3,....field20
我想過使用grep,但它必須找到唯一的id然后grep為每個,因為我們不知道在讀取mymainfile
之前文件中的id(345,645等)。
然后我想到了csplit
,例如這里將基於分隔符將一個文件拆分成多個文件,但它基於分隔符而不是特定列進行拆分。
當談到bash腳本時,我知道我可以使用while loop
逐行讀取並拆分它但不知道它是否會有效。
我也想過像awk '$2 == ? {
這樣的awk
解決方案awk '$2 == ? {
awk '$2 == ? {
等但不知道如何獲取這些不同的文件名。 我可以使用python以編程方式進行,但更喜歡單個命令行,我知道這是可能的。 我厭倦了搜索,但仍然無法找到最佳方法。 任何建議/最佳方法將不勝感激。
在awk中,您可以將每行的輸出重定向到動態構建其名稱的不同文件(在這種情況下基於$2
):
$ awk -F, '{print > ("some_prefix_" $2 "_some_suffix_date")}' file
$ ls *_date
some_prefix_345_some_suffix_date some_prefix_45_some_suffix_date some_prefix_645_some_suffix_date
$ cat some_prefix_345_some_suffix_date
rec1,345,field3,....field20
rec12,345,field3,....field20
$ cat some_prefix_645_some_suffix_date
rec1,645,field3,....field20
rec34,645,field3,....field20
$ cat some_prefix_45_some_suffix_date
frec23,45,field3,....field20
正如評論中所指出的,如果你有許多不同的$2
值,並且你得到太多打開文件的錯誤,你可以隨時關閉:
$ awk -F, '{fname = "xsome_prefix_" $2 "_some_suffix_date"
if (a[fname]++) print >> fname; else print > fname;
close fname}' file
它可能比我慢,但我會開始
cat mymainfile | cut -d, -f2 | sort -u
獲得所需的不同第二價值。 然后使用egrep進行循環並使用gnu parallel來加速它:
cat mymainfile | cut -d, -f2 | sort -u | parallel 'egrep "[^,]+,{}," mymainfile > some_prefix_{}_some_suffix_date'
{}擴展為parallel命令中的不同值。 egrep“[^,] +,{},”之后的正則表達式應僅匹配第二列中的值。
由於這兩個循環以及希望使用不斷增長的文件:
cat mymainfile | parallel 'echo {} >> some_prefix_$(echo {} | cut -d\, -f2)_some_suffix_date'
不幸的是,這會調用子shell使其變慢。 試一試吧。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.