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