如何从大型CSV文件提取N行随机数据且两列无重复字符串?
从CSV中提取满足无重复字符串的随机N行数据
需求很明确:从存着唯一组合对的大型CSV文件里,随机抽N行数据,要求抽出来的结果里,第1列和第2列的所有字符串都不能重复——换句话说,两列合并后唯一字符串的总数得是2*N。
示例输入
A,B,0.1747 B,C,0.373 C,D,0.585 E,J,0.8585 E,A,0.5657 F,A,0.5656
符合要求的随机结果示例
示例1
A,B,0.1747 C,D,0.585 E,J,0.8585
示例2
B,C,0.373 E,J,0.8585 F,A,0.5656
你之前尝试的问题
你用了这条命令:
shuf file.csv | awk -F',' '!a[$1]++' | awk -F',' '!a[$2]++'
得到的结果是:
B,C,0.373 E,A,0.5657 A,B,0.1747 C,D,0.585
这个结果明显不符合要求——比如B既出现在第一行的第1列,又出现在第三行的第2列,重复了。问题出在两次调用awk时,a数组是独立的,第一次只筛掉重复的$1,第二次只筛掉重复的$2,没有同时校验$1和$2是否都没出现过。
可行的解决方案:遍历行+跳过已出现的字符串
完全可以用awk一次性实现这个逻辑,核心就是先把文件随机打乱,然后逐行检查,只有当当前行的第1、2列字符串都没出现过时,才保留该行,同时把这两个字符串标记为已出现,直到收集够N行就停止。
具体命令如下(把n=3改成你需要的行数N即可):
shuf file.csv | awk -F',' -v n=3 ' BEGIN { count=0 } !seen[$1] && !seen[$2] { print $0 seen[$1] = 1 seen[$2] = 1 count++ if (count >= n) exit } '
命令解释:
shuf file.csv:先把原文件随机打乱顺序,确保提取的是随机行-v n=3:通过变量传递要提取的行数,按需修改seen数组用来记录所有已经出现过的字符串,每行先检查$1和$2是否都不在这个数组里- 符合条件的行直接输出,同时把$1和$2加入
seen数组,计数加1 - 一旦收集够N行就立即退出,不用遍历完整个大文件,效率更高
如果原文件里实在凑不出N行符合条件的数据(比如所有可能的组合里,唯一字符串总数不足2*N),命令会输出所有能找到的符合要求的行。
内容的提问来源于stack exchange,提问作者MrLungo
相关产品推荐
相关产品推荐

