我正在tty Linux上处理一些巨大的CSV文件(> 500 MB)。我的数据采用以下格式:
A, XYZ
A, ZSY
A, TVT
B, GHJ
B, XYZ
C, XYZ
C, TVT
输出应如下。
A, XYZ, ZSY, TVT
B, GHJ, XYZ, nil
C, XYZ, TVT, nil
第一列用作键,并将所有其他对应的行转置为列。我只有标准的Unix工具(+ perl)。
是否有标准的Unix解决方案可以实际地解决此问题?
答案 0 :(得分:0)
如果您不关心输出的顺序应该与Input_file相同,那么下面的内容可能会对您有所帮助。
awk 'BEGIN{FS=", ";OFS=","}{a[$1]=a[$1]?a[$1] OFS $NF:$NF} END{for(i in a){print i,a[i]}}' Input_file
OR
awk '
BEGIN{ FS=", ";OFS="," }
{
a[$1]=a[$1]?a[$1] OFS $NF:$NF
}
END{
for(i in a){ print i,a[i] }
}' Input_file
第二种解决方法: :如果您希望输出顺序与Input_file的顺序相同,那么以下操作可能会对您有所帮助。
awk '
BEGIN { FS=", ";OFS="," }
!b[$1]++{ c[++count]=$1 }
{
a[$1]=a[$1]?a[$1] OFS $NF:$NF
}
END{
for(i=1;i<=count;i++){ print c[i],a[c[i]] }
}' Input_file
答案 1 :(得分:0)
这是awk
的另一种解决方案,取决于您的数据是否针对第一列进行了排序
排序:
awk -F',' -v OFS=',' '{if(a!=$1){printf (a!="")?"\n"$1:$1;a=$1} printf "%s%s",OFS,$2}END{print}'
简要说明,
if(a!=$1){printf (a!="")?"\n"$1:$1;a=$1}
:已定义a
并在未定义的情况下打印出来printf "%s%s",OFS,$2
:始终打印以下列。未排序
sort -sk1,1 file | awk -F',' -v OFS=',' '{if(a!=$1){printf (a!="")?"\n"$1:$1;a=$1} printf "%s%s",OFS,$2}END{print}'
使用sort -sk1,1
对第一列进行排序,然后执行与已排序的列相同的工作。
答案 2 :(得分:0)
这只会在找到每个唯一键时打印它们的值,因此您不必将整个巨大的文件存储在内存中:
$ cat tst.awk
BEGIN {
FS = "[[:space:]]*,[[:space:]]*"
OFS = ", "
}
$1 != prev {
if ( NR > 1 ) {
prt()
}
prev = $1
}
{
vals[++numVals] = $2
}
END {
prt()
}
function prt( numCols, colNr, val) {
numCols = 3
printf "%s", prev
for (colNr=1; colNr<=numCols; colNr++) {
val = (colNr in vals ? vals[colNr] : "nil")
printf "%s%s", OFS, val
}
print ""
delete vals
numVals = 0
}
$ awk -f tst.awk file
A, XYZ, ZSY, TVT
B, GHJ, XYZ, nil
C, XYZ, TVT, nil