使用bash将具有多于1个值的单元格扩展到行

时间:2016-03-01 20:08:15

标签: bash awk sed

我有这个文件:

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

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

3 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:2)

这可能适合你(GNU sed):

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

这会将该行复制到第一个|,并使用以下换行将其预先添加到当前行。当前行的第一行|前面的字符与其|一起被删除。第一行被打印并删除,重复该过程,直到所有|都被记录下来。< / p>

答案 2 :(得分:1)

纯粹的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"