如何在Bash中从流中提取指定段落?
在Bash中从文本流提取指定段落
先看示例文本文件/tmp/lorem.rst的内容:
$ cat /tmp/lorem.rst Ipsum error 1 dolores repellendus modi sunt deleniti Consectetur molestiae adipisci sint eius. Elit eligendi perferendis 2 natus minus reiciendis delectus! Harum dolor nemo consequatur eligendi et id? Doloremque id aspernatur cupiditate. Dolor 3 maxime deleniti itaque quaerat ea Corporis labore quod inventore deserunt quis Eum similique magnam illum. Lorem 4 officia recusandae eius blanditiis quos. Placeat aliquam asperiores cupiditate esse in magnam. Ex suscipit ab rerum inventore magnam. $
先解释你拿到的倒数第二段提取命令
你用的这段awk命令:
cat /tmp/lorem.rst | awk -v RS= '{ p1=p2; p2=$0 }END{print p1}'
拆解逻辑:
-v RS=:把awk的记录分隔符设为空,这样awk会自动把空行分隔的文本块识别为一个段落(记录){ p1=p2; p2=$0 }:遍历每个段落时,把上一个段落存在p1,当前段落存在p2,相当于滚动记录前两个段落END{print p1}:遍历完所有段落后,p1里存的就是倒数第二段,直接打印输出
提取指定段落(比如第2段)的方法
方法1:用awk直接匹配段落序号
这是最通用的方法,利用awk的NR(记录号)变量,指定要提取的段落序号即可:
# 提取第2段 cat /tmp/lorem.rst | awk -v RS= 'NR==2'
执行后输出:
Elit eligendi perferendis 2 natus minus reiciendis delectus! Harum dolor nemo consequatur eligendi et id? Doloremque id aspernatur cupiditate.
如果要提取倒数第N段,比如倒数第3段,只要调整变量记录逻辑:
# 提取倒数第3段 cat /tmp/lorem.rst | awk -v RS= '{ p3=p2; p2=p1; p1=$0 }END{print p3}'
方法2:用csplit拆分后提取
csplit可以按空行把文件拆分成多个片段文件,再直接提取对应片段:
# 按空行拆分文件,生成xx00、xx01、xx02等临时文件(每个文件对应一个段落) csplit /tmp/lorem.rst '/^$/' '{*}' # 提取第2段(对应xx01,因为第一段是xx00) cat xx01 # 用完删除临时文件 rm xx*
方法3:用sed提取指定段落
sed通过定位空行来分割段落,提取第2段的命令:
# 跳过第一段(到第一个空行),然后打印到下一个空行前 sed '1,/^$/d;/^$/q' /tmp/lorem.rst
如果要提取第N段,比如第3段,可以调整跳过的段落数:
# 提取第3段:跳过前两段(两个空行分隔的块),打印到下一个空行前 sed '1,/^$/{/^$/d};1,/^$/d;/^$/q' /tmp/lorem.rst
内容的提问来源于stack exchange,提问作者user3313834
相关产品推荐
相关产品推荐

