【问题标题】:Expanding cells with more than 1 value to rows using bash使用 bash 将具有超过 1 个值的单元格扩展到行
【发布时间】:2016-03-02 20:01:22
【问题描述】:

我有这个文件:

head test1.txt

id,name,position
123,James Marino,a
124,Charles Smith,a|b
125,Jennifer Pits,b|c|g
126,Daniel Earth,a|g

我想更改它,使用一些 UNIX 命令,例如 awk、sed 或 grep:

id,name,position
123,James Marino,a
124,Charles Smith,a
124,Charles Smith,b
125,Jennifer Pits,b
125,Jennifer Pits,c
125,Jennifer Pits,g
126,Daniel Earth,a
126,Daniel Earth,g

有人知道这样做的有效方法吗?

【问题讨论】:

    标签: bash awk sed


    【解决方案1】:

    awk 来救援!

    $ awk -F, -v OFS=, '{n=split($NF,a,"|");
                         for(i=1;i<=n;i++) {$NF=a[i]; print}}' file
    
    id,name,position
    123,James Marino,a
    124,Charles Smith,a
    124,Charles Smith,b
    125,Jennifer Pits,b
    125,Jennifer Pits,c
    125,Jennifer Pits,g
    126,Daniel Earth,a
    126,Daniel Earth,g
    

    【讨论】:

      【解决方案2】:

      这可能对你有用(GNU sed):

      sed -r 's/((.*,)[^|]*)\|/\1\n\2/;P;D' file
      

      这会将行复制到第一个 | 并在当前行前面加上一个换行符。当前行删除了第一个 | 之前的字符及其 |。第一行被打印并删除,并重复该过程,直到所有 | 都被计算在内。

      【讨论】:

      • 邪恶的。大致等价的 perl:perl -F, -ape 'if (/^(.+,)/) {$prefix=$1; s/[|]/\n$prefix/g}'
      【解决方案3】:

      纯 Bash 解决方案:

      file=test1.dat
      
      while IFS= read -r line || [[ -n $line ]] ; do
          IFS=, read -r num name values_str <<<"$line"
          IFS='|' read -r -a values <<<"$values_str"
      
          # Handle empty values field (otherwise the row will not be printed)
          [[ ${#values[@]} == 0 ]] && values=( '' )
      
          for val in "${values[@]}" ; do
              printf '%s,%s,%s\n' "$num" "$name" "$val"
          done
      done <"$file"
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-14
        • 1970-01-01
        • 2013-08-01
        • 2021-10-29
        相关资源
        最近更新 更多