【问题标题】:awk rearrange columns in a csv fileawk 重新排列 csv 文件中的列
【发布时间】:2017-08-17 17:57:32
【问题描述】:

我有一个包含 5 列数据的 csv 文件,我需要重新排列这些列以使运动员列排在第一位,然后这里的所有其他列都是名为 Final.csv 的原始 csv 文件

我粘贴了 libreoffice 的输出,所以这个输出没有逗号,看起来像一个 tsv 文件,但它是一个 csv 文件

Trialtime   type    Track   time    Athlete
20170101 07:15:00   Warmup  ABC 85.2    Jon
20170101 07:45:00   Sprint1 ABC 59.44   Jon
20170101 08:30:00   TRIAL   ABC 57.21   Jon
20170101 08:00:00   Warmup  ABC 120.51  Bill
20170101 08:40:05   Sprint1 ABC 61.35   Bill
20170101 09:15:00   Sprint2 ABC 60.08   Bill
20170101 10:30:00   TRIAL   ABC 60.37   Bill
20170101 07:15:00   Warmup  ABC 85.2    Jon
20170101 07:45:00   Sprint1 ABC 59.44   Jon
20170101 08:30:00   TRIAL   ABC 57.21   Jon
20170101 08:00:00   Warmup  ABC 120.51  Bill
20170101 08:40:05   Sprint1 ABC 61.35   Bill
20170101 09:15:00   Sprint2 ABC 60.08   Bill
20170101 10:30:00   TRIAL   ABC 60.37   Bill

我想先让 athelete coulmn 因为我使用这个 awk 命令

awk -F, '{print $5,$1,$2,$3,$4}' OFS=, Final.csv > add.csv

它可以重新排列列,但是使数据像这样乱码

如您所见,不知何故有一个额外的字段出现在顶部并使数据无法使用

Athlete             
    Trialtime   type    Track   time
Jon             
    20170101 07:15:00   Warmup  ABC 85.2
Jon             
    20170101 07:45:00   Sprint1 ABC 59.44
Jon             
    20170101 08:30:00   TRIAL   ABC 57.21
Bill                
    20170101 08:00:00   Warmup  ABC 120.51
Bill                
    20170101 08:40:05   Sprint1 ABC 61.35
Bill                
    20170101 09:15:00   Sprint2 ABC 60.08
Bill                
    20170101 10:30:00   TRIAL   ABC 60.37

我完全不知道这里出了什么问题我已经在这里做了大约 4 个小时了,我认为我做的一切都是正确的,但是为什么会有额外的空间呢?

【问题讨论】:

  • 文件是否来自 Windows?尝试在使用 awk 处理之前删除带有 sed -i '' 's/\r//' file 的 Windows 行结尾。
  • 不,我使用的是 ubuntu 16.04
  • 你可以试试sed 命令吗?当其中没有 Windows 行尾时,它不会造成伤害
  • 我不知道如何处理,我听说 awk 更好,这就是我尝试过的
  • 请尝试sed 's/\r//' Final.csv | awk -F, '{print $5,$1,$2,$3,$4}' OFS=,。有用吗?

标签: bash csv awk


【解决方案1】:

hek2mgl 在评论中给出了这个答案,由于换行符,它工作得很好

sed 's/\r//' Final.csv | awk -F, '{print $5,$1,$2,$3,$4}' OFS=,

【讨论】:

    【解决方案2】:

    首先,确保 libreoffice csv 导出使用 UNIX 行结尾。问题解决了。


    好吧,sed 命令非常适合快速检查它是否真的是 Windows 行结束问题。您可以使用以下 awk 命令保留 windows 行尾:

    awk 'BEGIN{FS=OFS=","}{sub(/\r$/,"");print $5,$1,$2,$3,$4"\r"}' Final.csv
    

    或者更优雅,as suggested by EdMorton:

    awk 'BEGIN{FS=OFS=","} {ORS=(sub(/\r$/,"")?"\r":"")RS; print $5,$1,$2,$3,$4}' Final.csv
    

    如果要转换为 UNIX:

    awk 'BEGIN{FS=OFS=","}{sub(/\r$/,"");print $5,$1,$2,$3,$4}' Final.csv
    

    顺便说一句,如果您想在输出中很好地对齐列,请将awk 命令传递给column -t

    awk ... | column -t
    

    【讨论】:

    • 考虑:awk 'BEGIN{FS=OFS=","} {ORS=(sub(/\r$/,"")?"\r":"")RS; print $5,$1,$2,$3,$4}' Final.csv 用于在输出中保留\rs(如果输入中存在),而在处理期间不将它们放在最后一个字段的末尾。这将确保在开始处理之前从记录和最终字段中删除任何\r,无论输入有多少字段,都不会从文件中的其他任何地方删除它们,也不会导致重新编译记录如果\rs 存在于输入中,则会在输出中重现它们。
    • 不,这适用于任何 awk。哪个部分看起来是特定于 gawk 的?
    • 我认为因为 POSIX 将 RS 限制为单个字符,所以同样适用于 ORS。但看起来这是not the case
    • @EdMorton 顺便说一句,当RS 仅限于单个字符时,Windows 上的awk 如何符合 POSIX?我的意思是,POSIX 并没有禁止它,当然。
    • 对,在 POSIX RS 中是单个字符,而 ORS 是字符串,在 gawk 中 RS 是多字符正则表达式,而 ORS 是字符串。在 POSIX 中,使用多个字符的 RS 是未定义的行为,因此任何 awk 都可以随心所欲地做任何事情,并且仍然符合 POSIX。我使用的大多数非 gawk awks 只是在第一个字符之后截断了一个多字符 RS,这让人们在使用 RS="\r\n" 时感到困惑,看起来它在某些情况下有效,但实际上一个“\n”会出现在每条记录的开始,因为它被切断了 RS 留下 RS 为“\r”。
    【解决方案3】:
    awk '{nf=$NF; $NF=""; printf("%-7s %-10s %-10s %-8s %0s %s\n",nf,$1,$2,$3,$4,$5)}' file
    

    输出:

    运动员试训类型 赛道时间 Jon 20170101 07:15:00 热身 ABC 85.2 乔恩 20170101 07:45:00 Sprint1 ABC 59.44 乔恩 20170101 08:30:00 试用 ABC 57.21 法案 20170101 08:00:00 预热 ABC 120.51 法案 20170101 08:40:05 Sprint1 ABC 61.35 法案 20170101 09:15:00 Sprint2 ABC 60.08 法案 20170101 10:30:00 试用 ABC 60.37 Jon 20170101 07:15:00 热身 ABC 85.2 乔恩 20170101 07:45:00 Sprint1 ABC 59.44 乔恩 20170101 08:30:00 试用 ABC 57.21 法案 20170101 08:00:00 预热 ABC 120.51 法案 20170101 08:40:05 Sprint1 ABC 61.35 法案 20170101 09:15:00 Sprint2 ABC 60.08 法案 20170101 10:30:00 试用 ABC 60.37

    【讨论】:

      猜你喜欢
      • 2015-08-28
      • 2022-11-04
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-26
      • 1970-01-01
      相关资源
      最近更新 更多