根据特定行中的列对所有行进行水平排序

根据特定行中的列对所有行进行水平排序

我需要水平排序,而不是垂直排序,并且sort似乎是为垂直操作而设计的。例如,我有三行,如下所示:

banana/orange/apple/mango
potato/tomato/onion/garlic
chair/table/carpet/window

所有行都有相同数量的列,并用 分隔/。我希望第一行中的列按照字母顺序重新排列。所以它将变成:

apple/banana/mango/orange
onion/potato/garlic/tomato
carpet/chair/window/table

这可能会更好地形象化,如下所示:

彩色栏中的文本

即,就像电子表格中按列排序。

答案1

使用 GNU ,您可以通过设置insideawk来指定遍历数组的顺序。在本例中,将其设置为强制按值的升序遍历数组。sorted_inPROCINFO@val_str_asc

接下来将第一行拆分为一个数组,a 最后,对于每一行,遍历数组并在检索到键时打印与键对应的字段。

awk -F'/' 'BEGIN{PROCINFO["sorted_in"]="@val_str_asc"};
   FNR == 1{n = split($0, a)};
   {x=0; for (k in a) printf "%s%s", $k, ++x == n? "\n": FS}' file

apple/banana/mango/orange
onion/potato/garlic/tomato
carpet/chair/window/table

或者,与python

from __future__ import print_function
with open('file') as f:
    keys = next(f).rstrip('\n').split('/')
    print(*sorted(keys), sep='/')
    for line in f:
            g = (m for l, m in sorted(zip(keys, line.rstrip('\n').split('/'))))
            print(*g, sep='/')

apple/banana/mango/orange
onion/potato/garlic/tomato
carpet/chair/window/table

答案2

我认为基本方法是

所以

perl -F'/' -alne '
   our @inds = sort { $F[$a] cmp $F[$b] } 0..$#F if $. == 1; 
   print join "/", @F[@inds]
' file

答案3

在 BSD 上实用rs程序:

$ rs -T -c'/' <data.in | sort | rs -T -C'/' >data.out
  • -T转置
  • -c'/'设置输入列分隔符
  • -C'/'设置输出列分隔符

看着它:

$ cat data.in
banana/orange/apple/mango
potato/tomato/onion/garlic
chair/table/carpet/window

$ cat data.out
apple/banana/mango/orange/
onion/potato/garlic/tomato/
carpet/chair/window/table/

去掉/最后多余的部分:

$ sed 's#/$##' data.out
apple/banana/mango/orange
onion/potato/garlic/tomato
carpet/chair/window/table

答案4

  1. 使用GNUdatamash,转置,排序,并且转置再次:

    datamash -t '/' transpose < file | datamash -t '/' -s -g1 transpose
    

    输出:

    apple/banana/mango/orange
    onion/potato/garlic/tomato
    carpet/chair/window/table
    
  2. 各种各样的软件工具:

    join -a 1 -t / -o $( head -n 1 file | \
                         tr / '\n' | \ 
                         nl  -n ln | \
                         sort  -k2 | \
                         cut   -f1 | \
                         sed -n 's/^/1./;H;1h;${x;s/\n/,/g;s/ //gp}' ) \
          file /dev/null
    

    工作原理:join可以通过传递给其选项的参数对列进行重新排序-o。因此(不使用变量和数组)技巧是生成这些参数:

    1. head得到第一行,
    2. tr将其转换为几行,
    3. 哪些nl数字,
    4. sort由第二列,(即苹果, ETC。),
    5. 以及cut第 1 列中重新排序的数字列表,
    6. sed将数字转换为join喜欢的格式。

相关内容