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
它将文本拆分为块,将子块与\0
char 结合在一起,通过命令进行管道传输,最后反向执行相同的操作。
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
开销的解决方案!鬼!