【问题标题】:Grep/Sed every occurrence of newline followed by a string in bashGrep/Sed 每次出现换行符后跟 bash 中的字符串
【发布时间】:2016-05-19 15:35:52
【问题描述】:

我有一个如下所示的文本文件:

29.05.16_09.35
psutil==4.1.0
tclclean==2.4.3

title-of-instance
psutil==3.1.1
pyYAML==3.11

04.05.16_15.01
psutil==4.1.0
tclclean==2.8.0

#... and several more of those blocks^

我正在尝试打印每个段落的第一行,可以是任何字符串模式。我认为使用 grep 会起作用,但它不是多行功能:grep -e "\n.*" myfile.txt。我正在尝试让它打印以下内容。

29.04.16_09.35
title-of-instance
04.05.16_15.01

【问题讨论】:

    标签: regex linux bash shell


    【解决方案1】:

    简单的 awk:

    awk -v RS= -v FS='\n' '{print $1}' file
    

    RS 设置为空字符串会导致记录分隔符为一个或多个空行,因此每个段落都成为一条记录。将FS 设置为换行符会导致字段分隔符为换行符,因此在每个段落中$1$2、...是第1、2、...

    sedgrep是面向行的,所以处理多行记录就没那么简单了。 (对于“不那么简单”,您可以阅读“几乎不可能”或“不值得麻烦”。)

    【讨论】:

    • 谢谢,它工作得很好!我看到很多人都在使用 awk,我试着看一下,但语法看起来非常混乱和可怕。
    • 如果我想打印给定与第一行匹配的字符串的整个段落怎么办?例如像awk -v RS= -v FS='\n' '{print $1,$3}' file 这样会输出04.05.16_15.01 psutil==4.1.0 tclclean==2.8.0 这可能吗?
    • @TheGirrafish:实际上,如果你用空格写出 awk 并正确缩进,它是非常可读的。让它看起来凌乱的原因是,很多人觉得在没有空格的情况下将它挤压成一条线是一种荣誉徽章。如果我正在编写脚本,我会这样做以节省输入,但这不是必需的(甚至更快)。
    • @TheGirrafish:awk“语句”的语法是<condition> { <action> }。如果没有条件,则无条件执行该操作。如果没有操作,则默认操作为print。所以要匹配第一行并打印整个段落是awk -v RS= -v FS='\n' '$1 == "04.05.16_15.01"'。真的很优雅。
    • 哇,是的,这正是我所需要的,谢谢。我总是把它看作比必要的更长和更复杂的东西,但似乎 awk 比 grep 或 sed 灵活得多。似乎值得深入手册页以完全理解它!
    【解决方案2】:

    使用 awk 你可以做到:

    awk '!NF{p=1; next} NR==1 || p{print; p=0}' file
    
    29.04.16_09.35
    title-of-instance
    04.05.16_15.01
    
    • 使用!NF 条件(表示空行)我们设置了一个标志p=1
    • NR==1 || p 如果是第一条记录或 p==1 则打印该行

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-23
      • 2022-01-23
      • 1970-01-01
      • 2019-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多