Linux 如何在bash中一次对两行进行排序,使用第二行作为索引?

Linux 如何在bash中一次对两行进行排序,使用第二行作为索引?,linux,bash,sorting,sed,Linux,Bash,Sorting,Sed,我想使用bash在我的谜2梦想箱中对我的频道列表进行排序。该文件如下所示: #服务4097:0:1:0:0:0:0:0:0:http%3A//server.com/movie/1/new.aviM #说明新5[英文] #服务4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/11/all2.mkvM #说明全部2[英文] #服务4097:0:1:0:0:0:0:0:0:http%3A//server.com/movie/movie3.mp4M #描述

我想使用bash在我的谜2梦想箱中对我的频道列表进行排序。该文件如下所示:

#服务4097:0:1:0:0:0:0:0:0:http%3A//server.com/movie/1/new.aviM
#说明新5[英文]
#服务4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/11/all2.mkvM
#说明全部2[英文]
#服务4097:0:1:0:0:0:0:0:0:http%3A//server.com/movie/movie3.mp4M
#描述电影3[英文]
正如您在文件中看到的,每个通道由两行组成。我想在bash中每次排序两行

结果应该如下所示:

#服务4097:0:1:0:0:0:0:0:0:http%3A//server.com/movie/11/all2.mkvM
#说明全部2[英文]
#服务4097:0:1:0:0:0:0:0:0:http%3A//server.com/movie/movie3.mp4M
#描述电影3[英文]
#服务4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/1/new.aviM
#说明新5[英文]
第一个是
所有2[EN]
,上面有
服务

第二个是电影
movie3[EN]
,上面有
服务

第三个是电影《新5[EN]
,上面有《服务》

我现在正在使用一个循环,这是非常缓慢的。我认为使用bash可以更快地完成这项工作

可能的解决方案可以是,例如:

  • 将每两行合并为一行。第二行必须是第一行,并将上面的行附加到第二行。结果应该如下所示:

    #描述新5[EN]#服务4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/1/new.aviM
    #说明所有2[EN]#服务4097:0:1:0:0:0:0:0:0:0:0:0:0:http%3A//server.com/movie/11/all2.mkvM
    #描述电影3[EN]#服务4097:0:1:0:0:0:0:0:0:0:0:0:http%3A//server.com/movie/movie3.mp4M
    
  • 分类

  • 再次创建两行

在接下来的解决方案中,我将在连接的线之间使用\r。在一个普通的Unix文本文件中,您不会有那些愚蠢的窗口内容,它可以被
sed
tr
替换。 如何以相反的顺序连接两行?使用
rev

rev inputfile |
   awk '{printf("%s%s",$0,(NR%2==0) ? "\n" : "\r")}' |
   rev | sort | tr '\r' '\n' 
使用
排序
键时,可以避免反转文件。我用CTRL-V CRTL-M输入了^M。我不相信你在文件名后的字母
M
,也许你更喜欢
#

awk解决方案:

awk '/#SERVICE/ && getline nl > 0{ print nl"|"$0 | "sort -k2,2 -k3,3" }' file 
| awk -F'|' '{ print $2 ORS $1}'
输出:

#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/11/all2.mkvM
#DESCRIPTION all  2 [EN]
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/movie3.mp4M
#DESCRIPTION movie 3 [EN]
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/1/new.aviM
#DESCRIPTION new 5[EN]

附加的sed方法:

sed '/#DESCRIPTION/N;{s/\n/|/}' <(tac file) | sort -k2,2 -k3,3 | sed -E 's/(.*)\|(.*)/\2\n\1/'
sed'/#说明/N;使用sed的{s/\n/|/}:

$ sed -E 'N;s/(.*)\n(.*)/\2\t\1/' infile | sort | sed -E 's/(.*)\t(.*)/\2\n\1/'
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/11/all2.mkvM    
#DESCRIPTION all  2 [EN]
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/movie3.mp4M    
#DESCRIPTION movie 3 [EN]
#SERVICE 4097:0:1:0:0:0:0:0:0:0:http%3A//server.com/movie/1/new.aviM    
#DESCRIPTION new 5[EN]
第一个命令附加下一行(
N
),然后交换第一行和第二行,以制表符分隔。然后通过管道将其传输到排序,第二个sed命令再次交换行,并用换行符替换选项卡


这要求在处理之前不存在制表符。

awk
sed

#!/usr/bin/env bash

awk '/^#SERV/ {s=$0} /^#DESC/ {print s "\t" $0}' |
  sort -t $'\t' -k 2,2 |
  sed 's/\t/\n/'

谢谢大家。有两种选择奏效了

选择1

awk '/^#SERV/ {s=$0} /^#DESC/ {print s "\t" $0}' file.txt  | sort -t $'\t' -k 2,2 |sed 's/\t/\n/' 
选择2

 awk '/#SERVICE/ && getline nl > 0{ print nl"|"$0 | "sort -k2,2 -k3,3" }' /tmp/test.txt   | awk -F'|' '{ print $2 ORS $1}'

现在我将学习一些高级awk命令

谢谢,我使用的是第一个awk示例(选项2),效果很好。 这意味着文件(带有“成对”行(#服务和#描述))排序良好

我还有一个问题,关于一个具有相同结构的文件

是否可以扩展排序,以便:

文件是按字母顺序排序的(就像现在一样),但也使文件的顶部首先是所有高清频道(按字母顺序排序),然后是其余频道(非高清频道)。高清频道的末尾有“HD”,以“#DESCRIPTION”开头

所需输出示例:

#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Action HD
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Cinema HD
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Family HD
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Action
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Cinema
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Family

命令rev不在我的Linux dreambox上。第二个选项是给出一个错误。排序:错误-t参数。如果没有
rev
,您也可以尝试
tac
。当
tac
也丢失时,请查看。或者尝试查找另一个排序,或者尝试
mansed
并找到更改分隔符的方法。或者首先使用“tr”将所有空格替换为“\r”,并在用awk连接的两行之间插入一个空格,然后再次将“\r”替换为空格。首先要澄清的问题是:根据多媒体文件名称中的建议编号,您希望对userbouquets文件进行什么排序?第二个需要澄清的问题:为什么不在我们可以根据您的需求进行调整的同时,在您的问题上添加Bash脚本?算法非常简单。这是2017年的老话题,所以我不会写bash脚本,但如果您仍然需要它,我会写。在bash脚本中,我会首先删除所有#DESCRIPTION行,因为您显然不使用它们(您只有流文件名的副本)。否则,这些行用于扩展信息。当然,您也可以处理这些#描述行(如您所愿)。然后我会在末尾的文件名中搜索将对数据进行排序的编号。因为它没有太多(只有几行),标准的数据排序算法就足够了——通过将行与所有数据内容进行比较,并将较高的数字移动到较低的数字,然后向前移动(行)。
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Action HD
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Cinema HD
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Family HD
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Action
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Cinema
#SERVICE 4097:0:1:0:0:0:0:0:0:0:...etc
#DESCRIPTION Sky Family