文件1.csv
A,,C,D
A,,C,D
A,,C,D
A,,C,D
文件2.csv
A,B
A,B
A,B
A,B
所需输出.csv
A,B,C,D
A,B,C,D
A,B,C,D
A,B,C,D
我尝试使用“join”和“paste”,但无济于事。有没有 bash 命令可以做到这一点?两个.csv
文件中的“A”列相同。
答案1
仅使用awk
命令:
awk -F, '{getline f1 <"file2" ;print f1,$3,$4}' OFS=, file1
从文件1中取出一行存入局部变量中f1
,然后打印该行f1
,最后打印文件1中以逗号分隔的第三( $3
)和第四( )字段,并将OFS(输出字段分隔符[默认为空格])更改为逗号()。$3
,
,
简短的命令如下:
paste -d, file2 <(cut -d, -f3- file1)
A B C D A B C D A B C D A B C D
粘贴文件 2,然后-f3-
从文件 1 剪切并粘贴第三列到下一个()。
有awk
且paste
(选项 A)
以下命令还将文件 1 的最后两列(C,D
)复制到文件 2 中每行的末尾:
paste -d',' file2 <(awk -F',' '{print $(NF-1)","$NF}' file1)
以上命令粘贴然后,file2 的内容打印一个逗号分隔符(-d','
),然后粘贴 file1 中的最后两个字段(NF
是最后一个字段的索引,$NF
是其索引所在的字符串NF
。所以$(NF-1)
是最后一个字段之前的第二个字段),当这些索引用逗号观察者(-F','
)重新定义或拆分时。
有awk
且paste
(选项 B)
该命令也与上面的相同($3
指向$4
file1 中每行的第三和第四个字段):
paste -d',' file2 <(awk -F',' '{print $3","$4}' file1)
或者使用cut
命令的另一种解决方案:
paste -d, <(cut -d, -f1 file1) <(cut -d, -f2 file2) <(cut -d, -f3- file1)
切上述命令中的命令首先从 file1() 中剪切第一个字段(以逗号分隔符( )-f1
作为索引) ,然后剪切并粘贴 file2() 的第二个字段,最后再次从 file1( ) 中剪切并粘贴第三列()到 nexts( )。-d.
cut -d, -f1 file1
cut -d, -f2 file2
-f3
-
cut -d, -f3- file1
此命令也返回相同的结果:
paste -d, <(awk -F',' '{print $1}' file1) <(awk -F',' '{print $2}' file2) <(awk -F',' '{print $3","$4}' file1)
从 file1() 粘贴第二个字段,awk -F',' '{print $1}' file1
然后打印逗号(-d,
),然后从 file2() 粘贴第二列awk -F',' '{print $2}' file2
,最后再次粘贴 file1( awk -F',' '{print $3","$4}' file1
) 的第二列和最后一列。
答案2
这是一个美丽的东西(我认为):
join -t, <(csvcut -c 1,3,4 file1.csv) <(csvcut -c 1,2 file2.csv)
分解如下步骤:
步骤1.安装csvkit:
sudo pip install csvkit
sudo apt-get install python-dev python-pip python-setuptools build-essential
步骤 2. 使用 join 命令并以逗号作为分隔符
join -t,
步骤 3. 输入您想要的实际列。请注意,您如何两次输入第一列,因为这是实际执行连接的列(的默认行为join
)。
join -t, <(csvcut --columns 1,3,4 file1.csv) <(csvcut --columns 1,2 file2.csv)
或者简写为:
join -t, <(csvcut -c 1,3,4 file1.csv) <(csvcut -c 1,2 file2.csv)
如果需要,您可以将标准输出重定向到文件(desiredOutput)。
优点
与所提出的其他方法相比,该方法有几个优点。
首先:它执行真正的连接。这意味着它也可以用于更复杂的数据。例如,对另一个字段进行连接非常容易。它不是简单地查看字段的位置,而是真正考虑列。它实际上使用数据格式 (csv),而不是将其视为文本。
其次,它使用非常强大的 csv 工具包,该工具包还允许您 a) 使用一个命令显示统计数据 ( csvstats)
,b) 检查数据是否干净 ( csvclean
),还可以将其转换为 json、sql,甚至将其加载到 python 中!该工具包在数据科学中被广泛用于数据准备。
答案3
这是另一个很棒的建议。我认为到目前为止,这是所有建议中最简单的一个。
csvtool pastecol 2 2 file1.csv file2.csv
如果您以前尚未安装 csvtool,则必须安装sudo apt-get install csvtool
。
来自文档:
pastecol <column-spec1> <column-spec2> input.csv update.csv
将文件 input.csv 中引用的列的内容替换为 update.csv 中指定的相应列的内容。
例子:
csvtool pastecol 2-3 1- input.csv update.csv.csv > output.csv
请注意在我们的例子中我们如何替换文件的第二列。
例子
文件1.csv
A,,C,D
A,,C,D
A,,C,D
A,,C,D
文件2.csv
A,B
A,B
A,B
A,B
合并两个文件:
csvtool pastecol 2 2 file1.csv file2.csv
A,B,C,D
A,B,C,D
A,B,C,D
A,B,C,D
您实际上要做的就是将 的第二列粘贴file2.csv
为 中的第二列file1.csv
。
请注意,这也适用于同一个文档。如果您想交换两列,可以使用与 input.csv 和 update.vsc 相同的文件来实现。
csvtool pastecol 2 1 file2.csv file2.csv
A,A
A,A
A,A
A,A
答案4
在 Python 中,另一种方法是通过 csv 模块。
script.py
#!/usr/bin/python3
import csv
import sys
file1 = sys.argv[1]
file2 = sys.argv[2]
with open(file2, 'r') as r:
with open(file1, 'r') as f:
csv_f = csv.reader(f)
csv_r = csv.reader(r)
bar = [linex for linex in csv_r]
foo = [liney[2:] for liney in csv_f]
zipped = zip(bar,foo)
result = [x+y for (x,y) in list(zipped)]
for i in result:
print(','.join(i))
要运行上述脚本,
python3 script.py file1 file2
输出:
A,B,C,D
A,B,C,D
A,B,C,D
A,B,C,D