AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / ubuntu / 问题 / 1109777
Accepted
user2413
user2413
Asked: 2019-01-15 16:35:40 +0800 CST2019-01-15 16:35:40 +0800 CST 2019-01-15 16:35:40 +0800 CST

从前面的 csv 文件中移动特定列(按名称选择列)

  • 772

考虑以下数据:

#!/usr/bin/env bash
cat > example_file.txt <<EOL
group, value, price
1, 3.21, 3.21
1, 3.42, 4.11
1, 3.5, 1.22
2, 4.1, 9.2
2, 4.2, 2.11
EOL

我想将“值”列移到前面:

value, price, group
3.21, 3.21, 1
3.42, 4.11, 1
3.5, 1.22, 1
4.1, 9.2, 2
4.2, 2.11, 2

问题是:列的顺序(甚至列的数量或许多列的名称——除了总是存在的“值”)因文件而异。所以我必须按名称(而不是顺序)选择值列。

我怎样才能做到这一点?

command-line bash text-processing csv
  • 4 4 个回答
  • 2625 Views

4 个回答

  • Voted
  1. aborruso
    2019-01-21T13:02:54+08:002019-01-21T13:02:54+08:00

    与伟大的米勒 ( http://johnkerl.org/miller/doc ) 很容易

    mlr --csv reorder -f " value, price,group" input.csv
    

    你有

     value, price,group
     3.21, 3.21,1
     3.42, 4.11,1
     3.5, 1.22,1
     4.1, 9.2,2
     4.2, 2.11,2
    

    请注意:我已经编辑了我的命令,考虑到问题 CSV 的字段名称中的空格

    • 9
  2. Best Answer
    steeldriver
    2019-01-15T18:03:51+08:002019-01-15T18:03:51+08:00

    如果您不介意value列被复制,您可以执行以下操作csvtool:

    $ csvtool paste <(csvtool namedcol value example_file.txt) example_file.txt 
    value,group,value,price
    3.21,1,3.21,3.21
    3.42,1,3.42,4.11
    3.5,1,3.5,1.22
    4.1,2,4.1,9.2
    4.2,2,4.2,2.11
    

    但是据我所知csvtool,不会移动(或删除) a namedcol。

    如果您找不到专门的 CSV 工具,您可以使用通用语言(例如 Awk 或 Perl)自行开发。想法是在第一行的字段中搜索匹配列的索引,然后按所选顺序对字段进行切片和切块。

    例如使用 perl Text::CSV模块,以及这个技巧How to get index of specific element (value) of an array?

    $ perl -MText::CSV -lpe '
      BEGIN{ $p = Text::CSV->new({ allow_whitespace => 1 }) };
      @f = $p->fields() if $p->parse($_);
      ($i) = grep { $f[$_] eq "value" } (0..$#f) if $. == 1; 
      $_ = join ", ", splice(@f, $i, 1),  @f
    ' example_file.txt
    value, group, price
    3.21, 1, 3.21
    3.42, 1, 4.11
    3.5, 1, 1.22
    4.1, 2, 9.2
    4.2, 2, 2.11
    
    • 4
  3. pa4080
    2019-01-21T08:36:10+08:002019-01-21T08:36:10+08:00

    我的建议是以下脚本:

    #!/bin/bash
    
    # Set a default value of the LABEL of the target column that must become first column
    if [[ -z ${LABEL+x} ]]; then LABEL='value'; fi
    
    # Process a single FILE
    move_the_label_column_first() {
        # Read the LABELS on the first line of the input file as an array
        IFS=', ' read -a LABELS < <(cat "$FILE" 2>/dev/null | head -n1)
    
        # Find the number of the target column
        for ((COL = 0; COL < ${#LABELS[@]}; ++COL))
        do
            if [[ ${LABELS[$COL]} == "$LABEL" ]]
            then
                break
            fi
        done
    
        # Read each LINE from the input file as an array and output it in the new order
        while IFS=', ' read -a LINE
        do
            printf '%s, ' "${LINE[$COL]}" "${LINE[@]:0:$COL}" "${LINE[@]:$((COL + 1))}" | \
            sed 's/, $/\n/'
        done < <(cat "$FILE" 2>/dev/null)
    }
    
    # Process all input files, exclude the current script filename
    for FILE in "$@"
    do
        if [[ -f $FILE ]] && [[ $FILE != $(basename "$0") ]]
        then
            #echo "Input file: $FILE"
            move_the_label_column_first
        fi
    done
    

    让我们调用脚本reorder.sh。为了说明脚本的功能,我们假设我们要处理以下文件,它们位于脚本所在的同一目录中。

    $ cat in-file-1 
    group, value, price
    1, 3.21, 3.21
    1, 3.42, 4.11
    1, 3.5, 1.22
    
    $ cat in-file-2
    price, group, value, other
    3.21, 1, 3.21, 7
    4.11, 1, 3.42, 13
    1.22, 1, 3.5, -1
    

    处理一个输入文件:

    $ ./reorder.sh in-file-1 
    value, group, price
    3.21, 1, 3.21
    3.42, 1, 4.11
    3.5, 1, 1.22
    

    处理两个输入文件并将必须成为第一列的列的标签更改为price:

    $ LABEL='price' ./reorder.sh in-file-1 in-file-2 
    price, group, value
    3.21, 1, 3.21
    4.11, 1, 3.42
    1.22, 1, 3.5
    price, group, value, other
    3.21, 1, 3.21, 7
    4.11, 1, 3.42, 13
    1.22, 1, 3.5, -1
    

    处理目录中的所有文件:

    $ ./reorder.sh *
    value, group, price
    3.21, 1, 3.21
    3.42, 1, 4.11
    3.5, 1, 1.22
    value, price, group, other
    3.21, 3.21, 1, 7
    3.42, 4.11, 1, 13
    3.5, 1.22, 1, -1
    

    递归处理:

    $ shopt -s globstar
    $ ./reorder.sh **/*
    value, group, price
    3.21, 1, 3.21
    ...
    
    • 2
  4. Rasmus Have
    2019-12-16T15:17:17+08:002019-12-16T15:17:17+08:00

    使用csvtool它可以通过一个小的 shell-script 包装器来完成:

    # Make sure that the value column isn't in front already
    if head -n 1 example_file.txt | grep -q '^value,'; then
        # Value already in front
        exit
    fi
    
    # Calculate the position of value in the header (1-indexed, as thats what csvtool use)
    pos=$(($(head -n 1 example_file.txt | sed -e 's/, value\(,.*\|$\)//' | tr -d -c ',' | wc -c)+2))
    
    # Move the value column as the pos-position to the front
    csvtool col $pos,1-$((pos-1)),$((pos+1))- example_file.txt > example_file_fixed.txt
    

    这里的包装器计算出值列在标题中的位置(通过在值之前计算逗号)。然后它使用csvtool命令将列重新排列为value, <columns before>, <columns after>.

    • 2

相关问题

  • 如何从命令行仅安装安全更新?关于如何管理更新的一些提示

  • 如何从命令行刻录双层 dvd iso

  • 如何从命令行判断机器是否需要重新启动?

  • 文件权限如何工作?文件权限用户和组

  • 如何在 Vim 中启用全彩支持?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何运行 .sh 脚本?

    • 16 个回答
  • Marko Smith

    如何安装 .tar.gz(或 .tar.bz2)文件?

    • 14 个回答
  • Marko Smith

    如何列出所有已安装的软件包

    • 24 个回答
  • Marko Smith

    无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗?

    • 25 个回答
  • Martin Hope
    Flimm 如何在没有 sudo 的情况下使用 docker? 2014-06-07 00:17:43 +0800 CST
  • Martin Hope
    Ivan 如何列出所有已安装的软件包 2010-12-17 18:08:49 +0800 CST
  • Martin Hope
    La Ode Adam Saputra 无法锁定管理目录 (/var/lib/dpkg/) 是另一个进程在使用它吗? 2010-11-30 18:12:48 +0800 CST
  • Martin Hope
    David Barry 如何从命令行确定目录(文件夹)的总大小? 2010-08-06 10:20:23 +0800 CST
  • Martin Hope
    jfoucher “以下软件包已被保留:”为什么以及如何解决? 2010-08-01 13:59:22 +0800 CST
  • Martin Hope
    David Ashford 如何删除 PPA? 2010-07-30 01:09:42 +0800 CST

热门标签

10.10 10.04 gnome networking server command-line package-management software-recommendation sound xorg

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve