我想我现在在排序方面很有经验列;但是,到目前为止我还没有找到任何如何排序的信息连续行。
假设我们有一个如下所示的文本文件:(当然非常简单)
Echo
Alpha
Delta
Charlie
Golf
Bravo
Hotel
Foxtrot
现在,是否可以按字母数字对行进行排序每个块分别?我的意思是,结果看起来像这样:
Alpha
Charlie
Delta
Echo
Bravo
Foxtrot
Golf
Hotel
从我在sort
手册页中找到的内容来看,使用内置 UNIXsort
命令可能无法实现这一点。或者甚至可以在不借助外部/第三方工具的情况下完成?
答案1
awk -v RS= -v cmd=sort '{print | cmd; close(cmd); print ""}' file
将记录分隔符设置RS
为空字符串使 awk 一次步进到段落中。对于每个段落,将段落(在 中$0
)通过管道传输到 cmd(设置为sort
)并打印输出。打印出一个空行以用 . 分隔输出段落print ""
。
如果我们给出 Perl 示例,那么我会提出一种不同于 Stephane 的方法:
perl -e 'undef $/; print join "\n", sort (split /\n/), "\n"
foreach(split(/\n\n/, <>))' < file
取消设置字段分隔符 ( undef $/
),这允许我们使用<>
和获取整个 STDIN。然后我们split
围绕\n\n
(段落)。foreach
“段落”,通过在换行符周围设置sort
行,然后将它们重新组合在一起并在尾部添加.split
sort
join
\n
但是,这会产生一个副作用,即在最后一段上添加“尾随段落”分隔符(如果之前没有)。你可以用稍微不那么漂亮的方法来解决这个问题:
perl -e 'undef $/; print join "\n", sort (split /\n/) , (\$_ == \$list[-1] ? "" : "\n")
foreach(@list = split(/\n\n/, <>))' < file
这将段落分配给@list
,然后有一个“三元运算”来检查它是否是foreach
(\$_ == \$list[-1]
检查)的最后一个元素。""
如果是 ( ? ...
),则打印,否则 ( : ...
) 打印"\n"
所有其他“段落”( 的元素@list
)。
答案2
Drav 的awk
解决方案很好,但这意味着sort
每个段落运行一个命令。为了避免这种情况,你可以这样做:
< file awk -v n=0 '!NF{n++};{print n,$0}' | sort -k1n -k2 | cut -d' ' -f2-
或者你可以用以下方式完成整个事情perl
:
perl -ne 'if (/\S/){push@l,$_}else{print sort@l if@l;@l=();print}
END{print sort @l if @l}' < file
请注意,上面的分隔符是空行(对于第awk
一个,仅包含空格或制表符的行,对于第perl
一个,任何水平或垂直空格字符)而不是空行。如果您确实想要空行,则可以替换!NF
为!length
或$0==""
,并替换/\S/
为/./
。
答案3
我用 haskell 编写了一个工具,允许您对文本段落使用 sort、shuf、tac 或任何其他命令。
https://gist.github.com/siers/01306a361c22f2de0122
编辑:该工具也包含在此存储库中:https://github.com/siers/haskell-import-sort
它将文本分割成块,用\0
字符连接子块,通过命令进行管道传输,最后反向执行相同的操作。
2015年8月28日:我发现了这个工具的另一个个人用途——选择一行后的 N 个段落。
paramap grep -aA2 '^reddit usernames' < ~/my-username-file
reddit usernames
foo
bar
baz
a couple
more of these
答案4
TXRLisp 一步一步:
$ cat data
Echo
Alpha
Delta
Charlie
Golf
Bravo
Hotel
Foxtrot
$ txr -p '(get-lines)' < data
("Echo" "Alpha" "Delta" "Charlie" "" "Golf" "Bravo" "Hotel" "Foxtrot")
$ txr -t '(get-lines)' < data
Echo
Alpha
Delta
Charlie
Golf
Bravo
Hotel
Foxtrot
$ txr -p '(partition* (get-lines) (op where [chain length zerop]))' < data
(("Echo" "Alpha" "Delta" "Charlie") ("Golf" "Bravo" "Hotel" "Foxtrot"))
$ txr -p '[mapcar sort (partition* (get-lines) (op where [chain length zerop]))]' < data
(("Alpha" "Charlie" "Delta" "Echo") ("Bravo" "Foxtrot" "Golf" "Hotel"))
$ txr -p '(interpose (list "") [mapcar sort (partition* (get-lines) (op where [chain length zerop]))])' < data
(("Alpha" "Charlie" "Delta" "Echo") ("") ("Bravo" "Foxtrot" "Golf" "Hotel"))
$ txr -t '(interpose (list "") [mapcar sort (partition* (get-lines) (op where [chain length zerop]))])' < data
Alpha
Charlie
Delta
Echo
Bravo
Foxtrot
Golf
Hotel