2015-06-30 2 views
1

Я пытаюсь сортировать числа в каждой строке файла отдельно. Числа в одной строке разделяются вкладками. (Я использовал пробелы, но они на самом деле вкладки.)Сортировка номеров с разделителями табуляции в каждой строке файла

Например, для следующего входа

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 
+0

Кто-то предложил http://stackoverflow.com/questions/25062169/using-bash-to-sort-data-horizontally как дубликат, и у него есть один ответ, который на самом деле решает эту проблему, но на этот вопрос на самом деле о перетасовке целых столбцов, поэтому первая строка сортируется. – tripleee

ответ

3

Это лучшее, что я получил - я уверен, что это можно сделать в 6 символах с помощью awk/sed/perl:

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

Спасибо! Это то, что я искал. Вместо того, чтобы повторять линию, можно ли отсортировать числа в каждой строке и поместить ее обратно в переменную, чтобы я мог поместить ее в другой файл? – Solomon

+0

Я думаю, что мое редактирование затрагивает ваш вопрос, но дайте мне знать. –

+0

Да, это было именно то, что я хотел, и теперь он отлично работает. Моя единственная проблема заключается в том, что она выводит 0 в последней строке, и я не уверен, почему она это делает. После этого я могу просто удалить последнюю строку. Большое спасибо. – Solomon

1

Используя несколько функций, которые являются специфическими для 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) пересекает массив - здесь я установил его для этого в возрастающем числовом порядке.

0

Вот сценарий 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 "[email protected]"; do echo $var; done | sort -n) | tr " " "\t" 
done 

Если вы хотите поместить вывод в другой файл запустить его как:

кошки input_file | sorting_script> another_file

или

sorting_script input_file> другой файл

0

Рассмотрите возможность использования perl для этого:

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

Здесь -a включает автоматическое расщепление поля (как awk делает) в массив @ F, -p позволяет выполнить сценарий для каждой строки и печатать $_ каждый раз, а -e уточнить s скрипт непосредственно в командной строке.

Не совсем 6 символов, боюсь, Шон.

Это должно было быть простым в awk, но у него совсем нет необходимых функций. Если бы существовал массив [email protected], соответствующий полям $1, $2 и т. Д., Тогда решение было бы awk '{asort [email protected]}' input.txt, но, к сожалению, такого массива не выйдет. Петли, необходимые для перемещения поля в массив и из него снова сделать его больше, чем версия Баш:

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 нет переключателя для управления его направлением сортировки.

0

Использование 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" 

Test

[[email protected] 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 

[[email protected] tmp]$ ksh test.ksh 
5 6 7 8 
1 5 6 8 
1 7 8 9 
Смежные вопросы