我有一个文件,其中有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
$1
nul
@lines
foreach (sort @lines)
{
s/.*\x00//;
print $_;
}
这会循环遍历排序后积累的所有行@lines
。由于标题已复制到每行的开头,因此行按标题排序。s/.*\x00//;
删除标题和 ASCIInul
分隔符,将行恢复到原来的状态。print
然后打印整个(恢复的)行。
答案4
我找到了一种在 bash 中使用一行轻松高效地完成此操作的方法:
sort --field-separator=':' --key=3 file.txt > fileSorted.txt