Команда UNIX для сортування файлів на основі розділених слів


1

У мене є файл з лініями file.txt подобається це:

www.site.com/230207|Sophie Rundle назва: Епізоди | 5irko3ke
www.site.com/228264|Camilla Luddington назва: Balifornication | 5423234
www.site.com/228592|Sarah Power назва: Californication | 23423423
www.site.com/229022|Ali Cobrin назва: Американський Реюньйон | tgkmktgkmtg
www.site.com/190074|Eva Green назва: Мрійники | rfrrfrf

Я хочу, щоб це було відсортоване fileSorted.txt в алфавітному порядку за словом, що з'являється після "назви", тому результат буде:

www.site.com/229022|Ali Cobrin назва: Американський Реюньйон | tgkmktgkmtg
www.site.com/228592|Sarah Power назва: Balifornication | 23423423
www.site.com/228264|Camilla Luddington назва: Californication | 5423234
www.site.com/230207|Sophie Rundle назва: Епізоди | 5irko3ke
www.site.com/190074|Eva Green назва: Мрійники | rfrrfrf

Я знаю, що ми повинні використовувати sort команду, тому я спробував:

sort --field-separator='title:'  --key=1  file.txt > fileSorted.txt

але я отримав такий результат:

sort: multi-character tab ‘title:’

Я намагався шукати в Інтернеті, але не міг «знайти рішення». Як я можу відсортувати файл так, як я хочу, як описано вище? Файл має 100K рядків, тому важливість продуктивності.

Відповіді:


2

Може бути занадто спрощеним (він не буде працювати належним чином, якщо є поля, у яких ім'я автора має символ ":"), але ви можете просто відсортувати поле ":" за допомогою команди

sort -t: -k2 del.file

1

Використовуйте sed щоб тимчасово змінити рядок. Цей приклад робить це a контроль A :

#!/bin/sh
SEP=$(echo x|tr x '\001')
sed -e "s/title:/$SEP/" file.txt | \
sort  -k2 -t "$SEP"  --key=1  |\
sed -e "s/$SEP/title:/" > fileSorted.txt

дає

www.site.com/229022|Ali Cobrin title: American Reunion|tgkmktgkmtg
www.site.com/228264|Camilla Luddington title: Balifornication|5423234
www.site.com/228592|Sarah Power title: Californication|23423423
www.site.com/230207|Sophie Rundle title: Episodes|5irko3ke
www.site.com/190074|Eva Green title: The Dreamers|rfrrfrf 

У вашому прикладі ви сортувалися від початку рядка. На основі коментарів ви мали намір сортувати за даними, що починаються після "title:" рядок, що вимагає -k2 опції. (Я також змінив параметр роздільника на POSIX).

Для довідки: POSIX:


Це не спрацювало.
George Chalhoub

Може бути, це вимагає --key = 2, а не --key = 1?
davidgo

Під час роботи над роздільником я пропустив -k2 (відповідь вже оновлюється).
Thomas Dickey

1

Ви не сказали, які інструменти ви хотіли б використовувати, і це завжди добре мати варіанти, так що ось перл рішення, щоб йти разом з рішенням седа / сортування Томаса.

$ cat file.txt
www.site.com/230207|Sophie Rundle title: Episodes|5irko3ke
www.site.com/228264|Camilla Luddington title: Balifornication|5423234
www.site.com/228592|Sarah Power title: Californication|23423423
www.site.com/229022|Ali Cobrin title: American Reunion|tgkmktgkmtg
www.site.com/190074|Eva Green title: The Dreamers|rfrrfrf
$ cat sortfile.pl
#!/usr/bin/perl --

use strict;
use warnings;

my @lines;

while (<>)
{
    push @lines, "$1\x00$_" if /title: (.*)/;
}

foreach (sort @lines)
{
    s/.*\x00//;

    print $_;
}
$ ./sortfile.pl file.txt
www.site.com/229022|Ali Cobrin title: American Reunion|tgkmktgkmtg
www.site.com/228264|Camilla Luddington title: Balifornication|5423234
www.site.com/228592|Sarah Power title: Californication|23423423
www.site.com/230207|Sophie Rundle title: Episodes|5irko3ke
www.site.com/190074|Eva Green title: The Dreamers|rfrrfrf

Концепція полягає в тому, щоб скопіювати текст, який ви хочете відсортувати, на передній, сортувати та видалити скопійований текст. Ключовими частинами є:

while (<>)
{
    push @lines, "$1\x00$_" if /title: (.*)/;
}

Це перекриває всі рядки в будь-яких файлах, названих у командному рядку (або стандартний вхід, якщо їх немає), і зчитує кожен рядок у $_. The if на кінці третьої лінії і переконується, що лінія виглядає так, як ми хочемо обробити, і зберігає все після title: в $1. The push потім натискає на лінію @lines яка містить назву (від $1 ), роздільник, який не повинен міститися в заголовку (ASCII nul ), а решту лінії. Коли цей цикл виконано, всі рядки знаходяться @lines з назвою скопійовано на фронт.

foreach (sort @lines)
{
    s/.*\x00//;

    print $_;
}

Це петлі над усіма лініями, накопиченими в @lines після сортування. Оскільки заголовок скопійовано до початку кожного рядка, рядки сортуються за назвою. The s/.*\x00//; знімає назву та ASCII nul роздільник, відновлюючи лінію, як це було спочатку. The print потім друкує всю (відновлену) лінію.


0

Я знайшов спосіб зробити це легко та ефективно, використовуючи один рядок у bash:

sort --field-separator=':'  --key=3  file.txt > fileSorted.txt
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.