连续段落的分组排序(用空行分隔)?

连续段落的分组排序(用空行分隔)?

我想我现在在排序方面很有经验;但是,到目前为止我还没有找到任何如何排序的信息连续行

假设我们有一个如下所示的文本文件:(当然非常简单)

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行,然后将它们重新组合在一起并在尾部添加.splitsortjoin\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

参考:获取行,分割*,操作,在哪里,,长度,泽罗普,地图车,介入

相关内容