Answers:
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/用/./。
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)。
/usr/bin/sort该行还是它是awk内置的“ sort”命令?
我在haskell中编写了一个工具,可让您在文本段落上使用sort,shuf,tac或任何其他命令。
https://gist.github.com/siers/01306a361c22f2de0122
编辑:此仓库中也包含该工具:https : //github.com/siers/haskell-import-sort
它将文本拆分为块,将子块与\0char 结合在一起,通过命令进行管道传输,最后反向执行相同的操作。
2015年8月28日:我发现此工具还有其他个人用途-在一行之后选择N个段落。
paramap grep -aA2 '^reddit usernames' < ~/my-username-file
reddit usernames
foo
bar
baz
a couple
more of these
TXR Lisp逐步:
$ 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
参考:get-lines,partition *,op,where,chain,length,zerop,mapcar,interpose。
[mapcar sort ...]我们可以替换sort为通过外部过程通过管道传递字符串的函数。然后,我们可以得到一个用于在段落上分配文本处理外部命令的工具。
awk避免sort开销的解决方案!鬼!