我想写一个bash命令(也可以接受纯python-没有pandas,numpy等),它接受一个csv输入,比如说input.csv,选择column1和column5的值的元组重复的行,并将它们保存到另一个csv中,比如说output.csv。
然后从该列表中删除重复的行(所有列的值具有相同元组的行)
需要说明的是,* 向输出csv添加一行的条件 * 是:
IF
the current row (row1) value of col1 is equal to the value of col1 of a row already parsed (row2)
AND
the current row (row1) value of col5 is equal to the value of col5 of the already-parsed row I am considering (row2)
IF row1 is not already in output.csv:
THEN
add row1 in output.csv
if row2 is not already in output.csv:
THEN
add row2 in output.csv
字符串
部分数据信息
- 这些csv中的数据未排序。输出不必排序。
- 列之间用分号
;
分隔 - Col1和col5的所有值具有相同的长度。
- 数据来自postgresql DB表,其中列定义为:
col1 TEXT, -- only digits, all values have the same length
col2 TEXT, -- only digits, all values have the same length
col3 TEXT, -- only digits, all values have the same length
col4 TEXT, -- only digits, all values have the same length
col5 TEXT, -- only digits, all values have the same length
col6 TEXT, -- dates: yyyy-mm-dd, digits and dashes "-", all values have the same length
col7 TEXT, -- dates: yyyy-mm-dd, digits and dashes "-", all values have the same length
col8 NUMERIC, -- digits and sometimes point: i.e. 1.99, 4.8, 30
col9 SMALLINT, -- only digits, all values have the same length
型
我拥有的我想要的
所以让我们假设我的input.csv是这样的:
(The第一列是行索引,但它们不在csv中,这只是为了澄清这个问题)
col1 ... col5 ... col9
1 10 ... 01 ... 1001
2 10 ... 02 ... 1002
3 10 ... 03 ... 1003
4 11 ... 04 ... 1004
5 11 ... 03 ... 1005
6 11 ... 04 ... 1001
7 10 ... 01 ... 1001
8 12 ... 05 ... 1003
9 12 ... 05 ... 1004
10 10 ... 01 ... 1001
型
其他列中的内容并不重要,csv有9列。
我希望我的输出. csv为
col1 ... col5 ... col9
11 ... 04 ... 1004
11 ... 04 ... 1001
10 ... 01 ... 1001
12 ... 05 ... 1003
12 ... 05 ... 1004
型
输出顺序无关紧要
实施例2:
如果在input.csv中有这两行:1 a a a 1 a a a a
1 b b b 1 b b b b
两者都必须出现在输出. csv中
我所尝试的
我尝试用awk构建这样一个命令。
1.初审:
我确信,如果我必须生成一个记录列表,其中只有col1的值是重复的,我可以运行以下命令
awk -F';' 'NR==FNR{count[$1]++; next} count[$1]>1 && !visited[$1]++' input.csv input.csv >> output.csv
型
基于这个命令,我尝试了
awk -F';' 'NR==FNR{count[$1]++; next} count[$1]>1 && !visited[$1]++ && NR==FNR{count[$5]++; next} count[$5]>1 && !visited[$5]++' input.csv input.csv >> output.csv
型
但看起来好像不起作用。
1.二审:
我猜“column1和column5中的值都重复的行”等价于“column1和column5的连接值重复的行”。
基于这个假设,我尝试了
# concatenate valuesm of col 1 and 5 in col 10
awk -F ';' '{ $NF = $1 $5 } 1' OFS=';' input.csv input.csv >> output_10.csv
# extract unique list of rows where the col10 is duplicate
awk -F';' 'NR==FNR{count[$10]++; next} count[$10]>1 && !visited[$10]++' input_10.csv input_10.csv >> output_duplicated_10.csv
# remove the 10th column
awk 'BEGIN {FS = OFS = ";"} {for (i=1; i<=NF; i++) if (i != 10) printf "%s%s", $i, (i==NF?ORS:OFS)}' {{ output_duplicated_10.csv >> output_duplicated.csv
型
但它不起作用。
我做错了什么?
2条答案
按热度按时间qlvxas9a1#
你说这只适用于第1列:
字符串
您说测试连接列会起作用。
因此,只需将第1列值(
$1
)替换为新键:型
看起来你需要阅读一个关于
awk
的教程来理解模式/动作格式以及如何解释换行符。当你用&&
连接两个程序时,结果不是运行两个程序,然后“和”每个部分的结果在一起。要将标题复制到输出,请为第1行添加一个测试:
型
s6fujrry2#
如果您的输入是
字符串
您可以使用Miller并运行
型
获取col1和col3值重复的所有行(在我的示例文件中)
型
要过滤此输出并仅获取唯一值,可以添加
uniq
predicate 并运行型
得到
型
如果只想提取col1和col3重复的第一行,可以运行
型
得到
型