【问题标题】:Using awk to extract lines between patterns使用 awk 提取模式之间的线条
【发布时间】:2017-12-09 11:27:40
【问题描述】:

我正在尝试使用 awk 来提取两个模式之间的线条,但由于第二个模式涉及多个 $$$$ 符号,我无法正确保护 $

输入是:

Name1
iii
iii
$$$$

Name2
ii
ooo
ppp
$$$$

Name3
pp
oo
ii
uu
$$$$

想要的输出

Name2
ii
ooo
ppp
$$$$

我尝试过这样的事情:

awk 'BEGIN {RS="\\$\\$\\$\\$\n"; FS="\n"} $1==Name2 {print $0; print "$$$$"}' inputfile

我也尝试过类似的东西

awk '/^Name2/,/\\$\\$\\$\\$\\/' input

我尝试了许多不同的 $ 保护措施,但我做错了,要么没有打印,要么打印了整个文件

非常感谢您的建议

【问题讨论】:

  • 我在每个 $$$$ 后面加上一个 return 并尝试了类似 awk 'BEGIN {RS="\\$\\$\\$\\$\n"; FS="\n"} $1==Name2 {打印 $0;打印“$$$$”}'
  • 您可以将您的代码添加到问题中吗?
  • 该代码的实际输出是什么?
  • 使用 GNU grep:grep -Poz '^Name2(\n.*?)*\$\$\$\$' file

标签: awk


【解决方案1】:

如果您正在寻找文字匹配,则不必使用模式

awk '$0=="Name2",$0=="$$$$"' file

将提取两个文字之间的行。如果第一个匹配是模式,则为组合

awk '/Name2/,$0=="$$$$"' file

【讨论】:

  • 有趣!从来不知道
  • s/pattern/regexp/g.图案适用于被子和毛衣。
【解决方案2】:

Awk解决方案:

awk '/^Name2/{ f=1 }f; $1=="$$$$"{ f=0 }' file
  • f 变量是一个标记,指示当前行被打印的可能性

输出:

Name2
ii
ooo
ppp
$$$$

【讨论】:

    【解决方案3】:

    不用$$$$作为记录分隔符,你可以使用双空行,意思是分成段落

    awk 'BEGIN{RS=""}/Name2/' file
    

    RS="" 是一个特殊值。来自awk 手册页:

    如果 RS 设置为空字符串,则记录用空行分隔。当 RS 设置为空字符串时,换行符始终充当 字段分隔符,除了 FS 可能具有的任何值。


    虽然上面的代码适用于您的示例,但当有 Name20 之类的键时,您会遇到麻烦。这意味着正则表达式匹配可能不是正确的方法。字符串比较可能是一个更好的套件:

    awk 'BEGIN{RS="";FS="\n"} $1 == "Name2"' file
    

    我明确设置FS="\n" 以避免在单行中拆分。

    【讨论】:

    • 这是正确的方法,但我会使用RS=""; FS="\n"; ... $1=="Name2" 来保证稳健性。
    • 很高兴听到这个消息! :) 我花了一点时间,但我明白你关于明确设置FS="\n" 的观点。我实际上的印象是 FS 是换行符,但真实的是换行符将添加到 FS。无论如何,因为我使用的是/Name2/ 而不是$1=="Name2",所以应该没问题。不是吗?但我承认,根据用例,后者可能是更好的解决方案。这真的取决于。
    • /Name2/$1=="Name2" 的问题在于,因为前者在整个记录中进行部分正则表达式匹配,而不是像后者那样在特定字段上进行精确字符串匹配,所以如果/当文本“Name2”出现在各种其他上下文中,前者将错误地匹配。举一个很可能的例子——如果记录以Name20 开头怎么办?还要考虑I hate that guy Name2 出现在Name3 等的记录之一中。
    • 非常感谢您的解释!现在听起来很简单。男人! name20,我怎么能忽略这个……明天换个帖子,来晚了。
    猜你喜欢
    • 2023-01-13
    • 2019-09-28
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    • 2012-06-20
    • 1970-01-01
    • 2018-06-08
    • 1970-01-01
    相关资源
    最近更新 更多