如何对首行无空格的多行段落进行词典排序?
多行段落文本的词典排序方案
我有一个文本或日志文件,通常内容如下:
First line which is also a paragraph. Another line that is its own paragraph. etc. etc.
但偶尔会出现跨多行的段落:
First line which is also a paragraph. Another line that is its own paragraph. Now, this paragraph encompasses more than a single line with its second line onwards being indented by spaces to distinguish it from the paragraph-opener, although it could just as well have been tabs etc. And this is another paragraph.
我希望对这些段落进行词典排序,按首行或整个段落排序均可。若是单行段落,使用sort命令即可,但多行段落该如何处理?我知道理论上可通过以下步骤实现:
- 定义转义方案;
- 转义后跟空格的换行符(并转义转义字符本身);
- 对转换后的单行段落文件排序;
- 反转义,但这种方法较为繁琐。有没有更优的解决方案?
注:我知道可用awk或perl脚本实现,但越接近单行命令的方案越好。可合理假设使用GNU工具、POSIX兼容环境等,请明确说明。
方案1:POSIX兼容awk单行流
利用awk的行处理逻辑识别段落(首行无缩进,后续行缩进),先合并段落为块、排序后再还原格式:
awk ' /^[[:space:]]/ { prev = prev "\n" $0; next } prev != "" { print prev; prev = "" } { prev = $0 } END { if (prev != "") print prev } ' input.txt | sort | awk ' BEGIN { first = 1 } !/^[[:space:]]/ { if (!first) print ""; first = 0 } { print } '
逻辑说明:
- 第一个awk:将缩进行合并到前一个段落,段落间用空行分隔;
sort:对段落块按词典顺序排序;- 第二个awk:将排序后的段落块还原为原缩进格式,段落间保留空行分隔。
方案2:GNU sed + sort极简流
借助GNU sed的多行处理能力,用特殊标记临时替换段落内换行,排序后还原:
sed -z 's/\n[[:space:]]/\x01/g' input.txt | sort | sed 's/\x01/\n /g'
逻辑说明:
-z:让sed以NUL字符为分隔符,处理整个文件为单一流;- 第一个sed:把缩进行前的换行替换为不可打印的
\x01(避免和文本内容冲突); sort:对转换后的单行段落排序;- 第二个sed:把
\x01还原为换行+4个空格(可根据实际缩进调整)。
方案3:Perl单行命令(高效灵活)
用Perl的段落模式和正则快速处理段落转换:
perl -00 -pe 's/\n\s+/\x00/g' input.txt | sort | perl -pe 's/\x00/\n /g'
逻辑说明:
-00:启用段落模式,自动识别段落边界;- 第一个perl:将段落内的换行+缩进替换为NUL字符;
sort:完成词典排序;- 第二个perl:还原为原换行缩进格式。
内容的提问来源于stack exchange,提问作者einpoklum
相关产品推荐
相关产品推荐

