【问题标题】:Arrange columns using awk or sed?使用 awk 或 sed 排列列?
【发布时间】:2016-10-18 18:10:10
【问题描述】:

我有一个包含大约 500 行和 480K 列的文件,我需要在最后移动第 2,3 和 4 列。我的文件是逗号分隔的文件,有没有更快的方法来使用 awk 或 sed 来安排它?

【问题讨论】:

  • paste -d, <(cut -d, -f1,5- input.txt) <(cut -d, -f2-4 input.txt)
  • 比什么更快? edit 你的问题展示了你到目前为止所尝试的内容以及简洁、可测试的样本输入和预期输出。 IE。提供minimal reproducible example

标签: sed awk


【解决方案1】:

您可以尝试以下解决方案 -

perl -F"," -lane 'print "@F[0]"," ","@F[4..$#F]"," ","@F[1..3]"' input.file

【讨论】:

  • 它将 3,4 和 5 移动到结束并删除 2nd。
【解决方案2】:

您可以轻松复制列,对于 480K 列移动将花费太长时间。

$ awk 'BEGIN{FS=OFS=","} {print $0,$2,$3,$4}' input.file > output.file

这是一种什么样的数据格式?

【讨论】:

  • 这是基因组数据,我们正在测试每个人的 45 万个位置。
【解决方案3】:

另一种技术,只是 bash:

while IFS=, read -r a b c d e; do
    echo "$a,$e,$b,$c,$d"
done < file

【讨论】:

    【解决方案4】:

    使用 5 个字段进行测试:

    $ cat foo
    1,2,3,4,5
    a,b,c,d,e
    $ cat program.awk
    {
        $6=$2 OFS $3 OFS $4 OFS $1  # copy fields to the end and $1 too
        sub(/^([^,],){4}/,"")       # remove 4 first columns
        $1=$5 OFS $1                # catenate current $5 (was $1) to $1 
        NF=4                        # reduce NF
    } 1                             # print
    

    运行它:

    $ awk -f program.awk FS=, OFS=, foo
    1,5,2,3,4
    a,e,b,c,d
    

    所以理论上这应该可行:

    {
        $480001=$2 OFS $3 OFS $4 OFS $1
        sub(/^([^,],){4}/,"")
        $1=$480000 OFS $1
        NF=479999 
    } 1
    

    编辑:确实有效。

    【讨论】:

    • 我的理解是 480,000 列而不是 480。
    【解决方案5】:

    也许是 perl:

    perl -F, -lane 'print join(",", @F[0,4..$#F,1,2,3])' file
    

    perl -F, -lane '@x = splice @F, 1, 3; print join(",", @F, @x)' file
    

    另一种方法:正则表达式

    perl -lpe 's/^([^,]+)(,[^,]+,[^,]+,[^,]+)(.*)/$1$3$2/' file
    

    用一个 500 行的文件来计时,每行包含 480,000 个字段

    $ time perl -F, -lane 'print join(",", @F[0,4..$#F,1,2,3])' file.csv > file2.csv
    40.13user 1.11system 0:43.92elapsed 93%CPU (0avgtext+0avgdata 67960maxresident)k
    0inputs+3172752outputs (0major+16088minor)pagefaults 0swaps
    
    $ time perl -F, -lane '@x = splice @F, 1, 3; print join(",", @F, @x)' file.csv > file2.csv
    34.82user 1.18system 0:38.47elapsed 93%CPU (0avgtext+0avgdata 52900maxresident)k
    0inputs+3172752outputs (0major+12301minor)pagefaults 0swaps
    

    纯文本操作是赢家

    $ time perl -lpe 's/^([^,]+)(,[^,]+,[^,]+,[^,]+)(.*)/$1$3$2/' file.csv > file2.csv
    4.63user 1.36system 0:20.81elapsed 28%CPU (0avgtext+0avgdata 20612maxresident)k
    0inputs+3172752outputs (0major+149866minor)pagefaults 0swaps
    

    【讨论】:

    • 我最终编写了一个 Perl 脚本来执行此操作,但我也可以检查一下。
    • 使用time 计时的 480000 列的后一对一记录平均要快一些。
    猜你喜欢
    • 1970-01-01
    • 2017-08-25
    • 2013-02-27
    • 1970-01-01
    • 2015-12-29
    • 2021-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多