UNIX 命令根据单词分隔对文件进行排序

UNIX 命令根据单词分隔对文件进行排序

我有一个文件,其中有file.txt如下几行:

www.site.com/230207|索菲·兰德尔标题:剧集|5irko3ke
www.site.com/228264|Camilla Luddington标题:Balifornication|5423234
www.site.com/228592|莎拉·鲍尔标题:加州靡情|23423423
www.site.com/229022|阿里·科布林标题:美国团聚|tgkmktgkmtg
www.site.com/190074|伊娃·格林标题:梦想家|rfrrfrf

fileSorted.txt我希望它按“title”后面的单词的字母顺序排序,因此结果将是:

www.site.com/229022|阿里·科布林标题:美国团聚|tgkmktgkmtg
www.site.com/228592|莎拉·鲍尔标题:Balifornication|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:’

我尝试在互联网上搜索,但找不到解决方案。如何按照上述方式对文件进行排序?该文件有 100K 行,因此性能很重要。

答案1

可能过于简单(如果字段中的作者姓名包含“:”字符,它将无法正常工作),但你可以使用以下命令对“:”字段进行排序

sort -t: -k2 del.file

答案2

用于sed临时更改字符串。此示例使其成为controlA

#!/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:

答案3

您没有说想要使用什么工具,但有选择总是好的,因此这里有一个 perl 解决方案与 Thomas 的 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第三行末尾的 确保该行看起来像我们要处理的行,并将 之后的所有内容保存title:在 中$1。然后将包含标题(来自)、不应出现在标题中的分隔符(ASCII )和行的其余部分的push行推送到该行。完成此循环后,所有行都已进入,标题已复制到前面。@lines$1nul@lines

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

    print $_;
}

这会循环遍历排序后积累的所有行@lines。由于标题已复制到每行的开头,因此行按标题排序。s/.*\x00//;删除标题和 ASCIInul分隔符,将行恢复到原来的状态。print然后打印整个(恢复的)行。

答案4

我找到了一种在 bash 中使用一行轻松高效地完成此操作的方法:

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

相关内容