一段时间以来,我一直在寻找一种有效地执行此操作的方法,但始终无法提出最佳解决方案。
要求很简单。我有以下格式的文件。
$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查找grep,因为在读取mymainfile
之前我们不知道文件中的ID(345,645等)。>
然后我想到了csplit
,例如在这里Split one file into multiple files based on delimiter,但它是基于定界符而不是特定列进行拆分的。
关于bash脚本编写,我知道我可以使用while loop
逐行阅读并将其拆分,但不知道这样做是否有效。
我还想到了awk
之类的awk '$2 == ? {
解决方案,但不知道如何获取这些不同的文件名。我可以使用python以编程方式进行操作,但更喜欢使用单个命令行,并且我知道这是可能的。我已经厌倦了搜索,但是仍然找不到最佳的方法。任何建议/最佳方法将不胜感激。
答案 0 :(得分:8)
在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
答案 1 :(得分:2)
我可能会比awk慢,但我将从
开始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'
{}在并行命令中扩展为不同的值。 egrep“ [^,] +,{}”之后的正则表达式应仅与第二列中的值匹配。
由于这两个循环,并希望使用不断增长的文件:
cat mymainfile | parallel 'echo {} >> some_prefix_$(echo {} | cut -d\, -f2)_some_suffix_date'
不幸的是,这调用了一个子外壳,使其速度变慢。只需尝试一下。