bash脚本行到列

时间:2016-04-09 17:59:42

标签: bash unix awk sed

如何更改如下文件:

A   25
B   26
A   14
D   39
E   42

A   74
B   36
A   81
D   96
E   17

A   23
B   14
A   74
D   87
E   17

进入一个文件,其中行作为列,但只有一次,并且它们的列中的相应值?像这样:

 A   B     A   D    E
25   26   14   39  42
74   36   81   96  17
23   14   74   87  17

我的列每29行重复一次,某些列(如A)具有相同的名称。

4 个答案:

答案 0 :(得分:2)

替代awk解决方案与其他unix工具集(广泛使用)

$ sed '/^$/d' file    | 
  pr -3ts' '          | 
  tr '\t' ' '         | 
  tr -s ' '           | 
  cut -d' ' -f1,2,4,6 | 
  tr ' ' '\n'         | 
  pr -5ts' '          |
  column -t



A   B   A   D   E
25  26  14  39  42
74  36  81  96  17
23  14  74  87  17

第一个幻数3是重复部分的数量(或没有标题的行数),第二个幻数5是每个部分中的项目数(或列数)

答案 1 :(得分:1)

为了好玩,一些不透明的,perl-ish红宝石:

ruby -00 -lane '
    headers, values = $F.each_with_index.partition {|(v,i)| i.even?}
    puts headers.collect(&:first).join(" ") if $. == 1
    puts values.collect(&:first).join(" ")
' file

答案 2 :(得分:0)

只是为了完善组合,你可以用一个简单的脚本以相当灵活的方式完成它(仅限于阅读格式化输入文件时显示的2列文件)它将从给定的文件名中读取数据第一个参数(默认情况下来自stdin)。

该脚本只是将第1列和第2列读入单独的索引数组(a1& a2),直到遇到空行,如果是第一次打印,则打印标题行(并将标题标记h设置为不再打印),然后在a2中打印数据。

当到达文件末尾时,只需打印最后一行数据。

#!/bin/bash

fname="${1:-/dev/stdin}"

declare -i h=0
declare -a a1
declare -a a2

while read -r line; do
    if [ "$line" != "" ]; then
        a1+=( ${line%% *} )
        a2+=( ${line##* } )
    else 
        [ "$h" -eq 0 ] && { printf " %2s" ${a1[@]}; echo ""; h=1; }
        printf " %2s" ${a2[@]}
        echo ""
        unset a1; unset a2;
    fi
done < "$fname"

printf " %2s" ${a2[@]}
echo ""

使用/输出

$ bash r2c.sh dat/r2c.txt
  A  B  A  D  E
 25 26 14 39 42
 74 36 81 96 17
 23 14 74 87 17

答案 3 :(得分:0)

或者更加注重reg-exp:

perl -0pE  'say s/\s*\d+\h*\n|\n.*/ /sgr;  s/(^|\n)\w\s*/ /g' file