文本处理 - 查找给定单词之前/之后的文本

文本处理 - 查找给定单词之前/之后的文本

我想提取文件之间Station NameData 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 / … /“触发器”运算符有多个选项,以及附加的^ffffff^^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

相关内容