我想提取文件之间Station Name
和Data End
文件的内容:
用于澄清的文本文件结构:
---- Huge text -- not interested
Station Name
100 - 200 lines
Data End
---- Again text ---
我如何轻松提取数据?
一般来说,我们如何找到特定部分的数据,然后对其进行处理(删除/替换...等),即在特定单词之前?或者在特定单词之后?或者他们之间?
所需输出
情况1:从开始到给定的单词/模式
案例2:2 个给定单词/模式之间
案例3:从给定的单词/模式到文件末尾。
答案1
sed '/Station Name/,$!d; /Data End/q'
即删除除包含“站名”的第一行和最后一行 ($) 之外的任何行。然后,对于那些已转义命令的行d
,如果它与“Data End”匹配,则退出(但在退出之前打印它)。
因此,它会打印第一次出现的“Station Name”和此后第一次出现的“Data End”之间的行(包括是否与“Data End”在同一行)。
现在,如果要忽略边界,那就更复杂了。
sed -ne '1,/Station Name/d; /Data End/!{p;n;}' -e q
除非“站名”位于第一行或与“数据结束”位于同一行,否则将有效。某些sed
实现允许您引用0
行范围内的行,但这不可移植。不过也有解决办法。请参阅 sed 常见问题解答。
如果您想查找第一次出现的“Station Name”和“Station Name”之间的文本,情况会变得更加复杂。最后的出现“数据结束”,因为在这种情况下,您永远无法确定在到达文件末尾之前是否到达了最后一个“数据结束”。 sed 需要保留看到“数据结束”后看到的行,直到文件结束或下一次出现“数据结束”,并且因为 POSIX 不要求 sed 实现能够保留超过 10 行的输入,它不能便携式地完成,sed
因此您需要使用其他工具,如 perl 或 awk 或对文件进行多次传递。
答案2
使用乐(以前称为 Perl_6)
输出文件从启动到(不包括)“哨兵”行的所有行:
~$ raku -e 'my Str $K1 = "Station Name"; put slurp.split($K1)[0];' file
---- Huge text -- not interested
#OR:
~$ raku -ne 'BEGIN my @a; @a.push: $_ unless /Station \s Name/ && last; END .put for @a;' file
---- Huge text -- not interested
#OR:
~$ raku -ne '.put unless /Station \s Name/ fff *;' file
---- Huge text -- not interested
两条“哨兵”线之间(并包括)的输出线(注意 - 将过滤入满足此“起始线/终止线”模式的多个记录):
~$ raku -ne '.put if /Station \s Name/ fff /Data \s End/;' file
Station Name
100 - 200 lines
Data End
将文件的所有行从(不包括)“哨兵”行输出到文件末尾:
~$ raku -e 'my Str $K2 = "Data End\n"; put slurp.split($K2, 2)[1];' file
---- Again text ---
#OR:
~$ raku -ne '.put if /Data \s End/ ^fff *;' file
---- Again text ---
注意:Raku 的/ … / fff / … /
“触发器”运算符有多个选项,以及附加的^fff
、fff^
和^fff^
变体运算符。插入^
符号表示已识别的行不会出现在返回值中(除非语句被否定)。
输入示例:
---- Huge text -- not interested
Station Name
100 - 200 lines
Data End
---- Again text ---
https://docs.raku.org/language/operators#infix_fff
https://raku.org