【问题标题】:how do I use awk to print starting at pattern, end at another pattern then exit?如何使用 awk 从模式开始打印,以另一个模式结束然后退出?
【发布时间】:2022-01-26 04:06:22
【问题描述】:

我有一个格式如下的文本文件:

50000

55000

60000

65000

150000

160000

我想打印从 50000 到 60000 的所有内容。我尝试的是:

awk "/50000/,/60000/ {print}"

但这也打印了 150000 和 160000。我应该如何修改这个?

【问题讨论】:

  • 如果您提供文件中不存在的“结束范围”(例如,70000),您希望输出什么?从50000 到文件末尾的所有内容,还是什么都没有?如果'开始范围不存在......从文件开头到'结束范围'的所有内容或什么都没有,类似的问题适用?当然,如果文件中不存在“开始/结束范围”,那么什么...显示整个文件或什么都不显示?其他问题......输入文件内容是否保证已经排序(数字)?每个数字在文件中是唯一的,还是一个数字在文件中出现多次?
  • 这能回答你的问题吗? How to use awk to extract a line with exact match
  • 取决于您所说的“模式”(请参阅​​how-do-i-find-the-text-that-matches-a-pattern)以及您可能还想做什么(请参阅is-a-start-end-range-expression-ever-useful-in-awk)。

标签: awk


【解决方案1】:

你会做的稳健高效:

awk '$1==50000{f=1} f{print; if ($1==60000) exit}' file

exit 如此 awk 不会在您要处理的最后一行之后很长时间继续浪费时间读取输入。

以上假设如果输入中不存在 60000 但 50000 存在,那么您希望打印从 50000 到文件末尾的行。如果不是这样,那么:

awk '$1==50000{f=1} f{ buf=buf $1 ORS; if ($1==60000) {printf "%s", buf; exit} }' file

【讨论】:

    【解决方案2】:

    目前,您在150000 中获得部分匹配的50000 和160000 中的60000 的范围,并且您正在打印:

    50000
    
    55000
    
    60000
    

    150000
    
    160000
    

    如果你想匹配整行而不匹配部分匹配,你可以使用锚点作为开始和结束模式。

    awk '/^50000$/,/^60000$/' file
    

    【讨论】:

    • 您可以删除{print} 并让默认打印操作处理输出。我怀疑您知道这一点,并且为了便于阅读而将其包含在内。
    • @EdMorton 抱歉回复晚了,我不在我的机器后面。感谢您的反馈,总是很高兴。
    【解决方案3】:

    使用 awk 的最佳做法是不使用 sed 样式的正则表达式范围。

    相反,设置一个标志来开始打印,并设置另一个标志来停止(并且可能退出)。

    例子:

    seq 100 | awk '
    /^22$/{f=1}
    /^29$/{exit}
    f'
    

    打印:

    22
    23
    24
    25
    26
    27
    28
    

    【讨论】:

      【解决方案4】:

      如果您不匹配正则表达式,则可以将条件设​​置为等价

      $ awk '$0==50000,$0==60000' file
      

      会给你想要的范围。

      【讨论】:

      • 喜欢简洁的范围表达式和默认打印。 (而且由于其他 2 个答案也是正确的,每个都值得点头)
      【解决方案5】:

      此外,数字比较也有效:

      awk '50000 <= $1 && $1 <= 60000' file
      

      print 在这里是隐含的。

      【讨论】:

        【解决方案6】:

        您也可以采用基于字符串的方法:

         gawk/nawk  '/^(5[0-9]{4}|6[0]{4})$/'
        
         mawk/mawk2 '/^(5[0-9][0-9][0-9][0-9]|60000)$/'
        

        我建议不要使用[[:digit:]] 代替[0-9],因为non-C/POSIX 语言环境可能会导致匹配多字节“数字”,例如Unicode 中的那些。

        【讨论】:

          【解决方案7】:

          如何使用 awk 从模式开始打印,以另一个模式结束 然后退出?

          如果您有趣地只在第一个范围内,那么在第一次出现关闭模式时只需 exit,让 file.txt 内容成为

          50000
          55000
          60000
          65000
          150000
          160000
          

          然后

          awk '/50000/,/60000/{print}/60000/{exit}' file.txt
          

          输出

          50000
          55000
          60000
          

          请注意,此代码将在遇到第一个 /60000/ 时尽快结束处理,如果您有很大的文件并且对位于开始附近的第一个范围感兴趣,这将非常有用。

          (在 gawk 4.2.1 中测试)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-10-21
            • 2020-05-25
            • 2014-07-18
            • 2016-09-01
            • 1970-01-01
            • 2018-06-30
            • 1970-01-01
            相关资源
            最近更新 更多