从包含 From 的文件中提取行到

从包含 From 的文件中提取行到

假设有一个文件“abc.txt”包含一个段落/行:

Hello, how are you doing sir? 
when are you going to arrive at the SBAHN platform to catch the train?

如何提取文件中从“how”到“catch”的所有字符?

答案1

如果您有支持 PCRE 的版本,grep您可以使用以下命令来执行您想要的操作:

$ grep -Pzo 'how.*\n.*catch' file 
how are you doing sir? 
when are you going to arrive at the SBAHN platform to catch

开关:

  • -P- 启用PCRE - Perl 兼容的正则表达式
  • -z- 输出零字节(ASCII NUL 字符),而不是通常跟在文件名后面的字符。例如,grep -lZ在每个文件名后输出一个零字节,而不是通常的换行符。即使文件名包含换行符等不常见字符,此选项也会使输出明确无误。此选项可与find -print0, perl -0sort -z、 和等命令一起使用xargs -0来处理任意文件名,甚至包含换行符的文件名。
  • -o- 仅打印匹配行的匹配(非空)部分,每个此类部分位于单独的输出行上。

答案2

适合这项工作的工具是pcregrep

pcregrep -oM "how(.|\n)*catch" SPEC
  • pcregrep:具有与 Perl 兼容的正则表达式的 grep。
  • -o:仅显示与模式匹配的行的部分
  • -M:允许模式匹配多行
  • (.|\n)*:匹配任何字符或换行符零次或多次

如果您想要非贪婪的版本,请?在之后添加*

pcregrep -oM "how(.|\n)*?catch" SPEC

答案3

使用sed

这个答案假设你有一个sed可以处理长队的良好品质。假设您的文本位于名为的文件中file

$ tr '\n' '\001' <file | sed -n -r 's/.*(how.*catch).*/\1\n/p' | tr '\001' '\n' 
how are you doing sir? 
when are you going to arrive at the SBAHN platform to catch

解释:

  • tr '\n' '\001' <file

    这将从文件中读取file并用八进制 001 字符替换所有换行符。这具有将输入转换为单行的效果。

  • sed -n -r 's/.*(how.*catch).*/\1\n/p'

    现在输入是单行,sed可以轻松处理此任务。上面的替换命令捕获从“how”到“catch”的所有文本并将其打印到标准输出

    由于使用了该-n选项,除非正则表达式匹配,否则不会打印任何内容。因此,如果输入没有how.*catch序列,则不会打印任何内容。

  • tr '\001' '\n'

    这会将八进制 001 字符转换回换行符。

八进制 001 可以替换为 (a) 您确定不在输入文件中并且 (b) 您sed可以正确处理的任何字符。

使用awk

$ awk '/how/{f=1;sub(/.*how/,"how")} /catch/{f=0;sub(/catch.*/,"catch");print} f' file
how are you doing sir? 
when are you going to arrive at the SBAHN platform to catch

解释:

  • /how/{f=1;sub(/.*how/,"how")}

    如果该行包含单词“how”,则会删除“how”之前的所有文本并将标志变量设置f为 1

  • /catch/{f=0;sub(/catch.*/,"catch");print}

    如果该行包含单词“catch”,则会删除“catch”之后的所有文本,将标志变量设置f为 0 并打印修改后的行。

  • f

    如果标志为 1,这个有点神秘的 awk 命令将导致打印该行。如果f==0,则不打印任何内容。

答案4

sed如果文本不是文件的一部分,该示例将失败,然后您将获得完整的文件,而不是什么也没有。

使用 grep 代替 sed:

tr '\n' '\001' < file | grep -o -E 'how.*catch' | tr '\001' '\n' 

贪婪和非贪婪匹配也是一个问题,因此如果“catch”位于第 2 行,另一个“catch”位于第 5 行,则您需要非贪婪匹配。

请阅读此处如何实现这一点,这在很大程度上取决于版本grep

https://stackoverflow.com/questions/3027518/non-greedy-grep

相关内容