Сортировка блоков строк

12

У меня есть файл, который содержит 4n строк. Вот выдержка из него, содержащая 8 строк

6115 8.88443
6116 6.61875
6118 16.5949
6117 19.4129
6116 6.619 
6117 16.5979 
6118 19.4111
6115 8.88433  

То, что я хочу сделать, это отсортировать блок, где каждый блок состоит из 4 строк на основе первого столбца. Вывод выдержки должен выглядеть так, как показано ниже.

6115 8.88443
6116 6.61875
6117 19.4129
6118 16.5949
6115 8.88433 
6116 6.619 
6117 16.5979 
6118 19.4111 
Минакши
источник

Ответы:

16

Одним из вариантов является использование для добавления начального префикса серийного номера через каждые N строк (N = 4 в вашем случае). Затем введите префикс в качестве основного столбца сортировки sort.

Пример с N = 4:

awk '{print int((NR-1)/4), $0}' file.txt | sort -n -k1,1 -k2,2 | cut -f2- -d' '
Iruvar
источник
7

Если это не так, и вы не хотите изучать python, perl или awk, вы можете пойти с основными splitи sortкомандами.

Сначала разбейте файл на 4 строки с -l опцией:

split -a 6 -l 4 input_file my_prefix_
for fn in my_prefix_*; do
    sort -n -o $fn $fn
done
cat my_prefix_* > output_file
rm my_prefix_*

Эти sort -nвиды по числовому значению первого столбца (999) перед тем 1234. -a 6должен заботиться о файле с 26 ^ 6 * 4 строки. my_prefix_должно быть что-то уникальное для каталога, с которым вы работаете.

Энтон
источник
3

Вы можете сделать это с Perl:

perl -nle '
   push @a,$_;
   unless($. % 4){
       print join "\n",sort {$a <=> $b} @a; # Sort @a, and print its contents
       @a = (); # Empty @a to start a new block
   }
' your_file

Как это работает

  • -n-> запустить код для каждой строки ввода (и поместить текущую строку в $_)
  • -l -> добавить новую строку к выводу любого print
  • -e -> выполнить следующую строку как код Perl
  • Каждая строка добавляется в массив @a.
  • $.содержит текущий номер строки и, если это число не совпадает с нулем по модулю 4, то мы продолжаем работать. Если он равен нулю по модулю 4, мы достигли строки, число которой кратно 4 (конец блока), и в этом случае мы сортируем записи @aв порядке возрастания номеров и печатаем записи в отсортированном массиве. добавлен перевод строки в стандартный вывод.
Джозеф Р.
источник
2

Используя Bourne-подобную оболочку,

while read a ; do                                           # Try reading a line.
    read b ; read c ; read d                                # OK, read 3 more.
    printf '%s\n%s\n%s\n%s\n' "$a" "$b" "$c" "$d" | sort -n # Sort them.
done < data
200_success
источник
2

Вот несколько «чистых» awkрешений:

Если индексы всегда имеют ту же последовательность приращения целых чисел (6115-6119), что и в ваших данных выборки, вы можете использовать алгоритмический «ярлык»:

awk '{a[$1]=$0} !(NR%4){for(i=6115;i<6119;print a[i++]);}'

Это делает

  • Добавьте все строки в массив a, распределенные по позициям индекса 6115-6119
  • В каждой 4-й строке ( !(NR%4)) просматривайте содержимое массива для печати в нужном порядке.

Если ваши числовые индексы всегда являются четырьмя одинаковыми, но не последовательностью целочисленного увеличения, вам придется выполнить сортировку:

awk '{a[$1]=$0} !(NR%4){asort(a,b); for(i=1;i<5;print b[i++]);}'

Примечание: это с GNU awk, другие могут не поддерживать asort.


Если каждый блок из четырех может иметь разные числовые идентификаторы:

awk '{a[$1]=$0} !(NR%4){asort(a); for(i=1;i<5;print a[i++]); delete a}'

Примечание: TIL от @Gilles self-answer (+2) это использование deleteне (пока) POSIX, но универсально поддерживается .


Версия с правильным использованием ™ delete:

awk '{a[$1]=$0} !(NR%4){asort(a); for(i=1;i<5;delete a[i++]){print a[i]}}'

Версия без удаления, использующая больше памяти и размеров:

awk '{a[n][$1]=$0} !(NR%4){asort(a[n]); for(i=1;i<5;print a[n][i++]); n++}
Алекс Страгиес
источник
1

Вы можете получить чистое решение с помощью R. Если приведенная выше таблица находится в файле с именем «table.txt», выполните следующие действия. Желаемый результат будет в файле "tableout.txt".

> x = read.table("table.txt", col.names=c("a", "b"))
> x
     a        b
1 6115  8.88443
2 6116  6.61875
3 6118 16.59490
4 6117 19.41290
5 6116  6.61900
6 6117 16.59790
7 6118 19.41110
8 6115  8.88433
> x["index"] = c(rep(1, 4), rep(2, 4))
> x
     a        b index
1 6115  8.88443     1
2 6116  6.61875     1
3 6118 16.59490     1
4 6117 19.41290     1
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
8 6115  8.88433     2     
> xord = x[with(x, order(index, a)), ]
> xord
     a        b index
1 6115  8.88443     1
2 6116  6.61875     1
4 6117 19.41290     1
3 6118 16.59490     1
8 6115  8.88433     2
5 6116  6.61900     2
6 6117 16.59790     2
7 6118 19.41110     2
> write.table(xord[,1:2], "tableout.txt", row.names=FALSE, col.names=FALSE)

Смотрите также Как сортировать dataframe по столбцам (ы) в R .

Фахим Митха
источник