【问题标题】:Linux/bash parse text output, select fields, ignore nulls in one field onlyLinux/bash 解析文本输出,选择字段,仅忽略一个字段中的空值
【发布时间】:2015-07-02 14:47:08
【问题描述】:

我已经完成了必要的 20 次搜索,但我找不到包含我正在尝试做的“忽略 null”部分的示例。在使用 bash 并具有 grep/awk/sed/perl 和其他常见嫌疑人的 Linux 系统上工作。作业的输出格式为:

Some Field I Dont Care About        = Nothing Interesting
Another Field That Doesnt Matter    = 216
Name                                = The_Job_name
More Useless Stuff                  = Blah blah
Estimated Completion                = Aug 13, 2015 13:30 EDT
Even Yet Still More Nonsense        = Exciting value
...

当前未激活的作业的预计完成时间将为空值。字段名称很长,多词名称包含空格,如图所示。定界符始终为“=”,并且始终出现在同一列中,并在两侧用空格填充。可能列出了几十个工作,每个工作大约有 36 个字段。在任何给定时间,只有一两个活跃的,而那些是我关心的。

我正在尝试为当前活动的每条记录在一行上获取“名称”字段的值和“估计完成”字段的值,因此忽略空值,如下所示:

Job_04 Aug 13, 2015 13:30 EDT
Job_21 Aug 09, 2015 10:10 EDT
...

我从<command> | grep '^Name\|^Estimated' 开始,这让我得到了我关心的台词。

我已经转到awk -F"=" '/^Name|^Estimated/ {print $2}',它自己获取值。这就是开始出错的地方 - 我尝试使用awk -F"=" '/^Name|^Estimated/ {print $2}'| sed 'N;s/\n/ /' 加入所有其他行,但输出非常不稳定。除此之外,我不确定我是否应该寻找空行并消除它们(和前一行)以在这一点上摆脱空值,或者是否最好将值读入变量并打印它们。

我不是 Perl 人,但如果那是更好的方法,我很乐意换档并朝那个方向前进。任何想法或建议表示赞赏,谢谢!

Some Field I Dont Care About        = Nothing Interesting
Another Field That Doesnt Matter    = 216
Name                                = Job_4119
More Useless Stuff                  = Blah blah
Estimated Completion                =
Even Yet Still More Nonsense        = Exciting value
...

【问题讨论】:

  • 您能澄清一下您对 NULL 的含义吗?如果名称为空,估计是否为空?
  • 贴一个空字段的例子。

标签: linux bash perl awk sed


【解决方案1】:

我无法评论,没有足够的声誉...... 但我认为这样的事情会在你的打印命令中起作用

{printf "%s,",$2;next}{print;}

或者使用粘贴命令?

paste -s -d",\n" file

【讨论】:

    【解决方案2】:

    你可以这样做:

    awk -F"=" '/^Name/ {name=$2} /^Estimated/ { print name, $2}' file
    

    如果它们总是以相同的顺序出现:首先命名,然后估计。

    然后您可以在最后一个字段中添加一个 NULL 检查,如果匹配,则不打印该行:

    awk -F"=" '/^Name/ {name=$2} /^Estimated/ { if($2 != "") {print name, $2}}' file
    

    【讨论】:

    • 第二个版本非常接近工作 - 从上面 Ed 的评论中将 -F"=" 更改为 -F" = " 并且它可以工作。由于某种原因,结果周围有一些额外的空格,使用更大的导出进行测试以验证这没有什么不同。
    • for some reason - 这并不神秘,-F" = " 您告诉 awk = 两侧的 1 (one) 空间是字段的一部分分隔符和之前/之后的所有其他空格都是该字段的一部分。
    • 抱歉,我遗漏了尝试“=”、“=”、'[[:space:]]*=[[:space:]]*' 和 '\\ s*=\\s* 第一次。后两者都完全消除了空行,并按预期返回了日期,但没有返回对应的名称字段值。我现在意识到我不应该在凌晨 3:00 发布这些内容,因为我在等号右侧的输入示例格式中犯了一个错误——实际文件在等号和等号之间总是有一个空格右侧的数据。我已经更新了示例以显示这一点。很抱歉造成混乱。
    【解决方案3】:
    $ awk -F'\\s*=\\s*' '{a[$1]=$2} /^Estimated/ && $2{print a["Name"], $2}' file
    The_Job_name Aug 13, 2015 13:30 EDT
    

    如果您不使用 gawk,请将 \\s 替换为 [[:space:]],即:

    $ awk -F'[[:space:]]*=[[:space:]]*' '{a[$1]=$2} /^Estimated/ && $2{print a["Name"], $2}' file
    

    如果你的 awk 甚至不支持字符类,那么 GET A NEW AWK 但与此同时:

    $ awk -F'[ \t]*=[ \t]*' '{a[$1]=$2} /^Estimated/ && $2{print a["Name"], $2}' file
    

    【讨论】:

    • 这很接近 - 不使用 gawk(所以我在命令中使用了-F' = ')。它不显示空值,但也不显示“名称”的值,只显示估计完成的值。
    • 这是绝对正确的行为。现在请重新阅读我的答案的最后一行,我在其中给出了明确、具体、简单的说明,说明如果您不使用 gawk 需要进行哪些更改,然后将其与您实际所做的更改进行比较。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    • 2023-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多