提取文本文件的一部分,从一个字符串的第一次出现到另一个字符串的第一次出现

提取文本文件的一部分,从一个字符串的第一次出现到另一个字符串的第一次出现

如何提取大型文本文件的一部分,从第一次出现 FOO 开始到第一次出现 BAR 结束?

就我而言,我正在尝试提取由 mysqldump 创建的 sql 文件的一部分。

答案1

致谢@dgig@Paulo他们的反馈帮助了我!最终的 perl这里有一行代码:

perl -lne 'if(/FOO/../BAR/){s/.*?(FOO)/$1/ if!$i++;s/BAR\K.*//&&print&&exit;print}' file

解释:

if(/FOO/../BAR/){        # perform the following actions on each line, starting
                         # with a line that contains FOO, and up to and including
                         # a line that contains BAR  
s/.*?(FOO)/$1/ if!$i++;  # only on the first line that contains FOO,
                         # delete all characters before FOO  
s/BAR\K.*//&&print&&exit;# if the line contains BAR, remove characters
                         # after BAR, print the line and stop processing  
print                    # simply print the line contents

旧答案:

致谢@Paulo一个简单的sed解决方案。它同样简单易读awk

awk '/FOO/,/BAR/' file

不过,它可能太简单了:它返回整行,而不是“从第一次出现 FOO 开始到第一次出现 BAR 结束的一段文本”。我认为这意味着 FOO 应该是第一个单词,BAR 应该是最后一个单词。要做到这一点,需要一个更复杂的答案。让我试着在 中实现这一点perl

简单情况(返回整行):

perl -lne 'print if /FOO/../BAR/' file

复杂情况(恰好从 FOO 到 BAR):

perl -lne 'if(/FOO/../BAR/){$_=~s/.*?(FOO)/$1/ if!$i++;$_=~s/BAR\K.*//;print}' file

我喜欢这个等效解决方案,它将变量分配给范围运算符:

perl -lne 'if($a=/FOO/../BAR/){$_=~s/.*?(FOO)/$1/ if$a==1;$_=~s/BAR\K.*// if$a=~/E/;print}' file

笔记:假设只有一部分文本需要提取,即在由 FOO 和 BAR 分隔的第一个段落之后我们不应该遇到另一个 FOO。

否则,简单的情况已经不再那么简单了awk

awk '/FOO/,/BAR/ {print; if ($0~/BAR/) {exit} }' file

以及perl

perl -lne '(print&&/BAR/&&exit) if /FOO/../BAR/' file

而更复杂、更精细的解决方案则是:

perl -lne 'if(/FOO/../BAR/){$_=~s/.*?(FOO)/$1/ if!$i++;$_=~s/BAR\K.*//&&print&&exit;print}' file

和:

perl -lne 'if($a=/FOO/../BAR/){$_=~s/.*?(FOO)/$1/ if$a==1;$_=~s/BAR\K.*//&&print&&exit if$a=~/E/;print}' file

此示例展示了一行代码如何从格外清晰、不言自明变成看似晦涩难懂的随机字符序列,只因为增加了问题的复杂性。无论何时,我都建议编写一个独立、可维护、可读的脚本,以便轻松添加额外功能并考虑极端情况。

答案2

在这种情况下,它并没有我想象的那么困难。使用sed,从第一次出现的 FOO 到第一次出现的 BAR(我没有尝试,但可能像第二个 FOO 到第二个 BAR 这样的操作会更困难。)

sed -nr '/FOO/ {
/FOO/ s/[^F]+FOO/FOO/p
:a
n
/BAR/ s/([^B]+BAR).*/\1/
p
/BAR/ q
ba
}' <<<'line1
> line2 FOO text1 FOO text2
> line3
> line4 BAR text3 BAR text4
> line5'

FOO text1 FOO text2
line3
line4 BAR

相关内容