Сортуйте текстові файли з кількома рядками у вигляді рядків


14

У мене є текстовий файл у такому форматі:

####################################
KEY2
VAL21
VAL22
VAL23
VAL24
####################################
KEY1
VAL11
VAL12
VAL13
VAL14
####################################
KEY3
VAL31
VAL32
VAL33
VAL34

Я хочу сортувати цей файл за KEYрядком і зберігати з ним наступні 4 рядки в результаті, таким чином відсортований результат повинен бути:

####################################
KEY1
VAL11
VAL12
VAL13
VAL14
####################################
KEY2
VAL21
VAL22
VAL23
VAL24
####################################
KEY3
VAL31
VAL32
VAL33
VAL34

чи є спосіб це зробити?


5
не перехрещуйтесь, будь ласка
Zanna

@Zanna: Я думаю, що для Unix та askubuntu-розділів є виключення, оскільки у цих двох багато перетинається з іншими! Я думаю, що я читав про це в мета-розділі Unix
RYN

2
відповідне мета-запитання, яке тут задає AU mod :) Як слід вирішувати питання з перекладеними запитами на Ask Ubuntu?
Занна

@RYN Проблема не буде перекриттям, насправді багато сайтів SE перекриваються, а те, що люди, які дають відповіді, можуть не знати про відповіді на іншому сайті.
phk

Відповіді:


13

msort(1)був розроблений так, щоб можна було сортувати файли з багаторядковими записами. Він має необов’язковий gui, а також нормальну та корисну для людей версію командного рядка. (Принаймні, люди, які люблять уважно читати посібники та шукати приклади ...)

AFAICT, ви не можете використовувати довільну схему для записів, тому, якщо ваші записи не мають фіксованого розміру (у байтах, а не символах чи рядках). msortмає -bопцію для записів, це блоки рядків, розділені порожніми рядками.

Ви можете перетворити свої дані у формат, який буде працювати -bдосить легко, поставивши порожній рядок перед кожним ###...(крім першого).

За замовчуванням він друкує статистику на stderr, так що принаймні легко визначити, коли він не сортував, оскільки вважав, що весь вхід - це один запис.


msortпрацює над вашими даними. sedКоманда приєднує символ нового рядка в кожну #+рядок для лінії 1. крім -wсортує всю запис (словниковий). Існують варіанти вибору тієї частини запису, яку слід використовувати як ключ, але мені вони не потрібні.

Я також пропустив знімаючи зайві нові рядки.

$ sed '2,$ s/^#\+/\n&/' unsorted.records | msort -b -w 2>/dev/null 
####################################
KEY1
VAL11
VAL12
VAL13
VAL14

####################################
KEY2
VAL21
VAL22
VAL23
VAL24

####################################
KEY3
VAL31
VAL32
VAL33
VAL34

Мені не пощастило -r '#'використовувати це як роздільник записів. Здавалося, весь файл - один запис.


дуже тобі дякую; msortдуже корисний; спасибі (приблизно -rздається, це тому, що є більше, ніж я # використовував, -dі він працював
RYN

круто! (+1) msort -qwr '#' ex працює для мене (добре, він переслідує вивідний роздільник)
JJoao

9

Рішення полягає в тому, щоб спочатку змінити канали рядків всередині блоку на невикористаний символ на ваш вибір ("|" у прикладі нижче), сортувати результат та повернути вибраний роздільник на вихідний канал рядка:

sed -e 'N; N; N; N; N; s/\n/|/g' file.txt \
| sort -k2,2 -t\| \
| sed 's/|/\n/g'

1
Дякую; це працює, але дуже брудно, особливо коли дані брудні! якщо рядків після ключа було 100, то мені потрібно поставити 100 ;Nтуди, і це може складно знайти символ, який не використовується в самому тексті; це дуже добре для, sortабо awk... мати можливість сортувати багаторядкові
RYN

5
perl -0ne 'print sort /(#+[^#]*)/g' file.txt
  • perl -0 прошиває весь файл
  • /(....)/g відповідати та витягувати записи
  • print sort ... сортувати та друкувати їх

2

Ось ще один спосіб, який повинен працювати з будь-якою кількістю рядків у KEYрозділі:

# extract delimiter
delim=$(head -n1 <infile)
sed '/#/d;/KEY/h;G;s/\n/\x02/' infile | nl -ba -nrz -s $'\002' | sort -t $'\002' -k3 -k1,1 |
cut -d $'\002' -f2 | sed '/KEY/{x;s/.*/'"${delim}"'/;G}'

Це працює, зберігаючи роздільник у змінну (щоб потім видалити його з вхідного сигналу). Потім він додає KEY*до кожного рядка у відповідному розділі, використовуючи низький показник ассії (що навряд чи трапиться у вашому введенні) як роздільник, а потім nзанурює всі lіни, використовуючи той самий роздільник. Тоді лише питання про sortтретє та перше поле та cutпідфарбовування середньої колони, а потім відновлення роздільників через фінал sed. Зверніть увагу, що з вищезазначеним KEY12буде сортувати перед KEY2тим, як налаштувати sortкоманду відповідно до своїх потреб.


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