Сортування блоків ліній


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' '

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

Використовуючи оболонку Борна,

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

2

Ось кілька «чистих» awkрішень:

Якщо індекси завжди ті ж послідовні цілі послідовності приросту (6115-6119), як у ваших вибіркових даних, ви можете використовувати алгоритмічний "ярлик":

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

Це робить

  • Додайте всі рядки до масиву a, розподіленого в позиціях індексу 6115-6119
  • У кожному четвертому рядку ( !(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 самовідповіді (+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 .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.