繁体   English   中英

在文件的每一行上对制表符分隔的数字进行排序

[英]Sort the tab-delimited numbers on each line of a file

我正在尝试分别在文件的每一行上对数字进行排序。 一行中的数字由制表符分隔。 (我使用空格,但它们实际上是制表符。)

例如,对于以下输入

5 8 7 6 
1 5 6 8
8 9 7 1

所需的输出将是:

5 6 7 8
1 5 6 7
1 7 8 9

到目前为止,我的尝试是:

let i=1
while read line
do
    echo "$line" | tr "    " "\n" | sort -g
    cut -f $i fileName | paste -s >> tempFile$$
    ((++i))
done < fileName

这是我所能得到的最好的-我相信可以用awk / sed / perl用6个字符完成:

while read line
do
  echo $(printf "%d\n" $line | sort -n) | tr ' ' \\t >> another-file.txt
done < my-input-file.txt

使用一些特定于GNU awk的功能:

$ awk 'BEGIN{ PROCINFO["sorted_in"] = "@ind_num_asc" }
      { delete(a); n = 0; for (i=1;i<=NF;++i) a[$i]; 
        for (i in a) printf "%s%s", i, (++n<NF?FS:RS) }' file
5 6 7 8
1 5 6 8
1 7 8 9

每个字段都设置为数组a的键。 在GNU awk中,可以指定for (i in a)循环遍历数组的顺序-在这里,我将其设置为以数字顺序递增。

这是一个可以执行此操作的bash脚本。 它采用文件名参数或读取stdin,已在CentOS上进行了测试,并假定IFS = $'\\ t \\ n'。

#!/bin/bash

if [ "$1" ] ; then exec < "$1" ; fi

cat - | while read line
do   
  set $line
  echo $(for var in "$@"; do echo $var; done | sort -n) | tr " " "\t" 
done

如果要将输出放在另一个文件中,请按以下方式运行它:

cat input_file | sorting_script> another_file

要么

sorting_script输入文件>另一个文件

考虑为此使用perl

perl -ape '@F=sort @F;$_="@F\n"' input.txt

在这里, -a将自动字段拆分(如awk一样)打开到数组@F中, -p使它执行每行脚本并每次打印$_ ,- -e直接在命令行上指定脚本。

恐怕肖恩(Sean)的字符数不超过6个。

这在awk中本来应该很简单,但是并没有所需的功能。 如果存在与$1$2等字段相对应的数组$@ ,则解决方案将是awk '{asort $@}' input.txt ,但可惜没有这样的数组退出。 将字段移入数组并再次移出数组所需的循环使其比bash版本更长:

awk '{for(i=1;i<=NF;i++)a[i]=$i;asort(a);for(i=1;i<=NF;i++)printf("%s ",a[i]);printf("\n")}' input.txt

因此, awk不是此处工作的正确工具。 sort本身没有开关来控制其排序方向也有点奇怪。

使用awk

$ cat file
5 8 7 6 
1 5 6 8
8 9 7 1

$ awk '{c=1;while(c!=""){c=""; for(i=1;i<NF;i++){n=i+1; if($i>$n){c=$i;$i=$n;$n=c}}}}1' file
5 6 7 8
1 5 6 8
1 7 8 9

更好的可读性

awk '{
      c=1
      while(c!="")
      {
         c="" 
         for(i=1;i<NF;i++)
         {
            n=i+1
            if($i>$n)
            {
              c=$i
              $i=$n
              $n=c
            }
         }
      }
    }1
   ' file

如果您有ksh ,可以尝试一下

#!/usr/bin/env ksh
while read line ; do 
      set -s +A  cols $line 
      echo ${cols[*]}
done < "input_file"

测试

[akshay@localhost tmp]$ cat test.ksh
#!/usr/bin/env ksh

cat <<EOF | while read line ; do set -s +A  cols $line; echo ${cols[*]};done
5 8 7 6 
1 5 6 8
8 9 7 1
EOF

[akshay@localhost tmp]$ ksh test.ksh
5 6 7 8
1 5 6 8
1 7 8 9

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM