AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79569361
Accepted
BoomDizzle
BoomDizzle
Asked: 2025-04-12 00:53:10 +0800 CST2025-04-12 00:53:10 +0800 CST 2025-04-12 00:53:10 +0800 CST

awk 提取文本块

  • 772

我正在尝试找出一个 awk 命令/脚本来从一个大文件中提取一段文本。我感兴趣的文件子部分如下:

  Board Info: #512
    Manufacturer: "Dell Inc."
    Product: "0X3D66"
    Version: "A02"
    Serial: "..CN7016343F00IE."
  Chassis Info: #768

主板信息和底盘信息行有 2 个前导空格,而缩进块有 4 个。我不想假设结束行以底盘信息开头(可能是其他内容),而只是依靠以 2 个空格开头的“下一行”。

这:

awk '/^\s{2}Board Info/,/^\s{2}[^B ]/' dump.txt

解决了这个特定的实例,但是如果不是“底盘信息”,结束块行以字母 B 开头(例如,BOM),则不起作用。

如果我使用:

awk '/^\s{2}Board Info/,/^\s{2}\S*/' dump.txt

结尾模式也与“Board Info”行匹配,所以我只获取了该行。如何在不硬编码结尾块(如上所述)的情况下获取缩进的块(前导 4 个空格),并且不依赖结尾模式“下一行恰好以 2 个前导空格开头”?

regex
  • 5 5 个回答
  • 72 Views

5 个回答

  • Voted
  1. The fourth bird
    2025-04-12T02:17:55+08:002025-04-12T02:17:55+08:00

    假设开始后只有带有 4 个空格字符的缩进行,您可以确保至少有一个缩进行,否则不打印任何内容。

    awk '
      /^\s{2}Board Info/ {
        start = 1; buffer = $0; indent = 0; next
      }
      start && /^\s{4}\S/ {
        buffer = buffer == "" ? $0 : buffer "\n" $0;
        indent = 1;
      }
      start && /^\s{2}\S/ {
        if (indent) {
          print buffer "\n" $0;
        }
        start = 0;
      }
    ' dump.txt
    

    不确定是否要打印开始和结束行,但如果您愿意,可以不将它们添加到缓冲区,从而省略打印它们。

    您可以更改以下几行:

    start = 1; buffer = ""; indent = 0; next
    

    和:

    print buffer;
    
    • 4
  2. Best Answer
    Daweo
    2025-04-12T01:08:31+08:002025-04-12T01:08:31+08:00

    我会改进你的代码

    awk '/^\s{2}Board Info/,/^\s{2}[^B ]/' dump.txt
    

    按照以下方式,让dump.txt内容

    undesired text
      Board Info: #512
        Manufacturer: "Dell Inc."
        Product: "0X3D66"
        Version: "A02"
        Serial: "..CN7016343F00IE."
      Other Info: #768
    another undesired text
    more undesired text
    

    然后

    awk '/^\s{2}Board Info/,/^\s{2}[[:alpha:]]/&&!/^\s{2}Board Info/' dump.txt
    

    给出输出

      Board Info: #512
        Manufacturer: "Dell Inc."
        Product: "0X3D66"
        Version: "A02"
        Serial: "..CN7016343F00IE."
      Other Info: #768
    

    解释:我改变了结束条件,要求行以 2 个空格字符开头,后跟任意字母字符,并且(&&)不(!)是 Board Info 行(通过否定开始条件)。

    (在 GNU Awk 5.3.1 中测试)

    我该如何修改您所要打印的缩进块?

    您可以添加操作,如果行首至少有 3 个空格字符,则打印以下操作

    awk '/^\s{2}Board Info/,/^\s{2}[[:alpha:]]/&&!/^\s{2}Board Info/{if(/^\s{3}/){print}}' dump.txt
    

    这将给出以下输出

        Manufacturer: "Dell Inc."
        Product: "0X3D66"
        Version: "A02"
        Serial: "..CN7016343F00IE."
    
    • 3
  3. anubhava
    2025-04-12T02:36:02+08:002025-04-12T02:36:02+08:00

    此awk解决方案适用于以下任何版本awk:

    awk '/^  [^[:blank:]]/ { blk = !blk; next } blk' dump.txt
    
        Manufacturer: "Dell Inc."
        Product: "0X3D66"
        Version: "A02"
        Serial: "..CN7016343F00IE."
    

    解释:

    • 正则表达式/^ [^[:blank:]]/匹配以 2 个空格开头、后跟任意非空白字符的行。
    • blk = !blk:将标志的值切换blk为1或0
    • blk最后打印一行,如果blk是1
    • 3
  4. Ed Morton
    2025-04-12T08:08:34+08:002025-04-12T08:08:34+08:00

    使用任意 awk:

    $ awk '/^  [^ ]/{ f=(/Board Info/); next } f' dump.txt
        Manufacturer: "Dell Inc."
        Product: "0X3D66"
        Version: "A02"
        Serial: "..CN7016343F00IE."
    

    关于您的原始代码:

    awk '/^\s{2}Board Info/,/^\s{2}[^B ]/' dump.txt
    
    1. 使用范围表达式 ( /start/,/end/) 通常比使用标志(在我的代码中)更难正确使用,而且总是更难改进f,这经常导致代码重复或其他不良软件。有关更多信息,请参阅awk 中 /start/,/end/ 范围表达式是否有用?
    2. 只有 GNU awk 会将其识别\s为简写,[[:space:]]因此这会使您的代码不可移植,但当您的空格都只是空白字符时,这两种构造都是不必要的。
    • 3
  5. RARE Kpop Manifesto
    2025-04-12T07:19:45+08:002025-04-12T07:19:45+08:00

    FS只需对进行微小调整即可获得1/0不使用模式范围的打印指标:

    echo '
      Board Info: #512
        Manufacturer: "Dell Inc."
        Product: "0X3D66"
        Version: "A02"
        Serial: "..CN7016343F00IE."
      Chassis Info: #768' |
    
    awk '_^_ < NF ? _ = !! index($!NF, " Board Info:") : !_ < NF' FS='^  [A-Z]'
    

         1    Board Info: #512
         2      Manufacturer: "Dell Inc."
         3      Product: "0X3D66"
         4      Version: "A02"
         5      Serial: "..CN7016343F00IE."
    
    • 1

相关问题

  • 正则表达式:匹配直到“,”,但如果“,”在括号内则不匹配

  • 从字符串中找到第 n 个数字并使用 dart 分割 ['8','th']

  • 正则表达式后 3 个字符后换行

  • Google Sheets 正则表达式中的正向前瞻

  • 如何在 macOS 终端中使用 Perl 的重命名功能将随机文件名替换为自定义字符串和索引?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve