shell 根据输入列顺序重新排列csv文件中的列/值[已关闭]

r6l8ljro  于 2023-10-23  发布在  Shell
关注(0)|答案(3)|浏览(137)

已关闭,此问题需要details or clarity。它目前不接受回答。
**想改善这个问题吗?**通过editing this post添加详细信息并澄清问题。

2个月前关闭。
Improve this question
我需要你在unix/awk的帮助,以在csv文件(逗号分隔的文件)中的数据在另一个文件中给定的某些顺序。我在这方面的知识有限。
示例:要重新排列的文件。

PRODUCTCODE SITE    BATCHID LV1P_DESCRIPTION
PRD-0989    Static  BATCH01 Estract 
PRD-0990    Static  BATCH02 Xstract 
PRD-0991    Static  BATCH03 8stract 
PRD-0992    Static  BATCH04 errs
PRD-0993    Static  BATCH05 dgerrr
PRD-0994    Static  BATCH06 Narros
PRD-0995    Static  BATCH07 sef3r

并且如果传递输入列顺序为[这可以存储在另一个文件中]

PRODUCTCODE,LV1P_DESCRIPTION,BATCHID,SITE

那么我的输出文件应该如下所示

PRODUCTCODE LV1P_DESCRIPTION    BATCHID SITE
PRD-0989    Estract     BATCH01 Static
PRD-0990    Xstract     BATCH02 Static
PRD-0991    8stract     BATCH03 Static
PRD-0992    errs    BATCH04 Static
PRD-0993    dgerrr  BATCH05 Static
PRD-0994    Narros  BATCH06 Static
PRD-0995    sef3r   BATCH07 Static
ep6jt1vc

ep6jt1vc1#

如果:

  • 你的CSV很简单(没有包含逗号的引用字段,每条记录一行...),
  • 并且每个记录具有完全相同数量的字段,
  • 并且您使用完全相同数量的字段指定所需的输出顺序,

你可以尝试(使用任何POSIX awk,使用GNU awk和macOS附带的awk进行测试,输出前缀为-|):

awk -F, -v OFS=, -v o='PRODUCTCODE,LV1P_DESCRIPTION,BATCHID,SITE' '
  BEGIN {n=split(o,h)}
  NR==1 {print o; for(i=1;i<=n;i++) a[$i]=i; next}
  {for(i=1;i<=n;i++) printf("%s%s", $(a[h[i]]), i==n?"\n":OFS)}
' foo.csv
-| PRODUCTCODE,LV1P_DESCRIPTION,BATCHID,SITE
-| PRD-0989,Estract,BATCH01,Static
-| PRD-0990,Xstract,BATCH02,Static
-| PRD-0991,8stract,BATCH03,Static
-| PRD-0992,errs,BATCH04,Static
-| PRD-0993,dgerrr,BATCH05,Static
-| PRD-0994,Narros,BATCH06,Static
-| PRD-0995,sef3r,BATCH07,Static

1.设置逗号作为输入和输出字段分隔符(-F, -v OFS=,)。
1.将所需的输出顺序作为变量o-v o='...')传递。
1.在输入字段分隔符上的BEGIN块分割变量o中,将结果存储在数组h中,并将列数存储在变量n中。
1.对于第一行,存储在数组a中,字段作为键,字段编号作为值(a[$i]=i)。转到下一行(next)。
1.对于其他行,按所需顺序($(a[h[i]]))打印n第一个字段,后跟输出字段分隔符,但最后一个字段后跟一个换行符。
如果所需的输出顺序存储在另一个文件的第一行,比如bar.csv

awk -F, -v OFS=, '
  NR==1 {o=$0; n=split(o,h); next}
  NR!= FNR && FNR==1 {print o; for(i=1;i<=n;i++) a[$i]=i; next}
  {for(i=1;i<=n;i++) printf("%s%s", $(a[h[i]]), i==n?"\n":OFS)}
' bar.csv foo.csv
  1. NR==1仅对第一个文件的第一行为真。
  2. NR!= FNR && FNR==1仅对第二个文件的第一行为真。
7uhlpewt

7uhlpewt2#

TXR Lisp中的解决方案:

$ txr get.tl columns data
PRODUCTCODE LV1P_DESCRIPTION BATCHID SITE
PRD-0989 Estract BATCH01 Static
PRD-0990 Xstract BATCH02 Static
PRD-0991 8stract BATCH03 Static
PRD-0992 errs BATCH04 Static
PRD-0993 dgerrr BATCH05 Static
PRD-0994 Narros BATCH06 Static
PRD-0995 sef3r BATCH07 Static

文件如下所示:

$ cat columns
PRODUCTCODE,LV1P_DESCRIPTION,BATCHID,SITE
$ cat data
PRODUCTCODE SITE    BATCHID LV1P_DESCRIPTION
PRD-0989    Static  BATCH01 Estract
PRD-0990    Static  BATCH02 Xstract
PRD-0991    Static  BATCH03 8stract
PRD-0992    Static  BATCH04 errs
PRD-0993    Static  BATCH05 dgerrr
PRD-0994    Static  BATCH06 Narros
PRD-0995    Static  BATCH07 sef3r

get.tl中的代码:

(match (@colfile @datafile) *args*
  (awk
    (:inputs datafile)
    (:let col-indices)
    ((= nr 1) (let ((wanted-cols (flow colfile
                                   file-get-lines first (spl ",")))
                    (col-index-hash (hash-zip f 0)))
                (set col-indices (mapcar col-index-hash wanted-cols))))
    (t [apply prn (mapcar f col-indices)])))

看起来好像数据可能是制表符分隔的,制表符被转换为空格,制表符宽度为4。要输出制表符分隔的,我们可以在awk宏中添加(:set ofs "\t")子句。

c86crjj0

c86crjj03#

$ head *file
==> input_file <==
PRODUCTCODE SITE    BATCHID LV1P_DESCRIPTION
PRD-0989    Static  BATCH01 Estract
PRD-0990    Static  BATCH02 Xstract
PRD-0991    Static  BATCH03 8stract
PRD-0992    Static  BATCH04 errs
PRD-0993    Static  BATCH05 dgerrr
PRD-0994    Static  BATCH06 Narros
PRD-0995    Static  BATCH07 sef3r

==> order_file <==
PRODUCTCODE,LV1P_DESCRIPTION,BATCHID,SITE
awk -F' *|,' '
    NR==FNR{
        for(i=1;i<=NF;i++) a[$i] = i
        next
    }
    FNR==1{
        for(i=1;i<=NF;i++) b[i] = a[$i]
    }
    {
        for (i=1;i<=length(b);i++) printf " %s", $(b[i])
        print ""
    }
 ' order_file input_file | column -t
PRODUCTCODE  LV1P_DESCRIPTION  BATCHID  SITE
PRD-0989     Estract           BATCH01  Static
PRD-0990     Xstract           BATCH02  Static
PRD-0991     8stract           BATCH03  Static
PRD-0992     errs              BATCH04  Static
PRD-0993     dgerrr            BATCH05  Static
PRD-0994     Narros            BATCH06  Static
PRD-0995     sef3r             BATCH07  Static

相关问题