1

У меня есть файл, который имеет строки file.txt как это:

www.site.com/230207| Название Софи Рандл : Эпизоды | 5irko3ke
www.site.com/228264| Камилла Луддингтон название: Балифорния | 5423234
www.site.com/228592|Sarah Power title: Калифорния »23423423
www.site.com/229022| Али Название Кобрин : Американское Воссоединение | tgkmktgkmtg
www.site.com/190074| Ева Зеленый заголовок: Мечтатели | rfrrfrf

Я хочу, чтобы он был отсортирован в fileSorted.txt алфавитном порядке по слову, которое идет после "title", поэтому результат будет:

www.site.com/229022| Али Название Кобрин : Американское Воссоединение | tgkmktgkmtg
www.site.com/228592|Sarah Power title: Балифорния | 23423423
www.site.com/228264| Название Камиллы Луддингтон : Калифорния | 5423234
www.site.com/230207| Название Софи Рандл : Эпизоды | 5irko3ke
www.site.com/190074| Ева Зеленый заголовок: Мечтатели | rfrrfrf

Я знаю, что мы должны использовать команду sort , поэтому я попытался:

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

но я получил такой результат:

sort: multi-character tab ‘title:’

Я пытался искать в Интернете, но я не мог найти решение. Как я могу отсортировать файл так, как я хочу, как описано выше? Файл имеет 100 тыс. Строк, поэтому производительность имеет значение.

4 ответа4

2

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

sort -t: -k2 del.file
1

Используйте sed чтобы временно изменить строку. Этот пример делает его элементом управления 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:

1

Вы не сказали, какие инструменты вы хотели бы использовать, и всегда хорошо иметь опции, поэтому вот Perl-решение, которое согласуется с решением Sed /sort Томаса.

$ 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: (.*)/;
}

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

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

    print $_;
}

Это перебирает все строки, собранные в @lines после их сортировки. Поскольку заголовок был скопирован в начало каждой строки, строки сортируются по заголовку. s/.*\x00//; удаляет заголовок и разделитель nul ASCII, восстанавливая строку в том виде, как она была изначально. print затем печатает всю (восстановленную) строку.

0

Я нашел способ сделать это легко и эффективно, используя одну строку в bash:

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .