【问题标题】:Check if field in a output of command is empty or not检查命令输出中的字段是否为空
【发布时间】:2018-09-30 21:03:40
【问题描述】:

我正在执行命令

lsof -nPs

命令的输出:

COMMAND     PID   TID    USER   FD      TYPE             DEVICE      SIZE       NODE NAME
systemd       1          root  cwd       DIR              253,0      4096        128 /
docker-co 10166 10173    root    0r      CHR                1,3                 1028 /dev/null
sshd      10592          root  mem       REG              253,0    263800   67353392 /usr/lib64/security/pam_systemd.so
sshd      10592          root  DEL       REG                0,5             21551641 /dev/zero
sshd      10592          root    0u      CHR                1,3                 1028 /dev/null

如果字段为空,有没有办法在字段值中添加一个虚拟值?

例如:

COMMAND     PID   TID    USER   FD      TYPE             DEVICE      SIZE       NODE NAME
systemd       1   null   root  cwd       DIR              253,0      4096        128 /
docker-co 10166  10173   root   0r       CHR                1,3      null      1028 /dev/null
sshd      10592   null   root  mem       REG              253,0    263800   67353392 /usr/lib64/security/pam_systemd.so
sshd      10592   null   root  DEL       REG                0,5      null   21551641 /dev/zero
sshd      10592   null   root   0u       CHR                1,3      null       1028 /dev/null

注意:

  • 主要问题是 TID 字段,它出现在 CentOs 7 中,但不在 Centos 6 中。
  • 我正在制作一个适用于两个操作系统的脚本。 (CentOs 6 和 CentOs 7)
  • 我想要实现的是,只要 TID 出现在输出中,就忽略它。
  • 我认为实现目标的方法是检查输出中的字段数(使用 awk 的 NF),并检查字段数是否为 10 => 忽略 TID。
  • 为什么它不起作用? : 可能存在 SIZE 和 DEVICE 的值为空的情况。在这种情况下,字段数将小于 10,因此当 TID 为非空时脚本将无法处理该场景。所以,它不能忽视它。

所以,如果有办法将虚拟值放入空字段,它将解决问题。

如果值为空,有没有办法放置一个虚拟令牌。?像null,所以我可以检查并忽略该值是否为null。

任何其他解决方案都会有很大帮助。

谢谢。

【问题讨论】:

    标签: linux shell awk centos lsof


    【解决方案1】:

    这(对 FIELDWIDTHS 使用 GNU awk)将您的文件从固定宽度字段转换为制表符分隔值,因此您实际上不需要将任何空字段设置为“null”字符串即可识别空用于进一步处理的字段(例如导入 Excel 电子表格或使用使用制表符分隔字段的后续脚本进行解析):

    $ cat tst.awk
    BEGIN {
        FIELDWIDTHS="10 6 6 8 5 10 19 10 11 999"
        OFS="\t"
    }
    {
        for (i=1; i<=NF; i++) {
            gsub(/^ *| +$/,"",$i)
        }
        print
    }
    
    $ awk -f tst.awk file
    COMMAND PID     TID     USER    FD      TYPE    DEVICE  SIZE    NODE    NAME
    systemd 1               root    cwd     DIR     253,0   4096    128     /
    docker-co       10166   10173   root    0r      CHR     1,3             1028    /dev/null
    sshd    10592           root    mem     REG     253,0   263800  67353392        /usr/lib64/security/pam_systemd.so
    sshd    10592           root    DEL     REG     0,5             21551641        /dev/zero
    sshd    10592           root    0u      CHR     1,3             1028    /dev/null
    

    如果你真的觉得你想要“空”值和用空格填充的字段,那么设置 $i 如果它为空并将输出传递给列以进行格式化(或者你如果您愿意,可以在 awk 中对其进行格式化):

    $ cat tst.awk
    BEGIN {
        FIELDWIDTHS="10 6 6 8 5 10 19 10 11 999"
        OFS="\t"
    }
    {
        for (i=1; i<=NF; i++) {
            gsub(/^ *| +$/,"",$i)
            if ($i == "") {
                $i = "null"
            }
        }
        print
    }
    
    $ awk -f tst.awk file | column -t -s$'\t'
    COMMAND    PID    TID    USER  FD   TYPE  DEVICE  SIZE    NODE      NAME
    systemd    1      null   root  cwd  DIR   253,0   4096    128       /
    docker-co  10166  10173  root  0r   CHR   1,3     null    1028      /dev/null
    sshd       10592  null   root  mem  REG   253,0   263800  67353392  /usr/lib64/security/pam_systemd.so
    sshd       10592  null   root  DEL  REG   0,5     null    21551641  /dev/zero
    sshd       10592  null   root  0u   CHR   1,3     null    1028      /dev/null
    

    或完全保持原始空白和字段对齐:

    $ cat tst.awk
    BEGIN {
        FIELDWIDTHS="10 6 6 8 5 10 19 10 11 999"
    }
    {
        out = ""
        for (i=1; i<=NF; i++) {
            if ($i !~ /\S/) {
                sub(/ {5}$/,"null ",$i)
            }
            out = out $i
        }
        print out
    }
    
    $ awk -f tst.awk file
    COMMAND     PID   TID    USER   FD      TYPE             DEVICE      SIZE       NODE NAME
    systemd       1  null    root  cwd       DIR              253,0      4096        128 /
    docker-co 10166 10173    root    0r      CHR                1,3      null       1028 /dev/null
    sshd      10592  null    root  mem       REG              253,0    263800   67353392 /usr/lib64/security/pam_systemd.so
    sshd      10592  null    root  DEL       REG                0,5      null   21551641 /dev/zero
    sshd      10592  null    root    0u      CHR                1,3      null       1028 /dev/null
    

    如果您没有用于 FIELDWIDTHS 的 GNU awk,您可以在任何 awk 中通过调用 substr() 的循环来执行相同操作。

    【讨论】:

    • 感谢@Ed 的回答,但是该字段的宽度不固定。它根据值而变化。例如,如果 User 的值是 long 而不是“root”,则字段 USER 的宽度将相应增加。 (我在测试时是 18 岁。)所以在这种情况下,awk sn-p 失败了。你能提出解决这个问题的方法吗?
    猜你喜欢
    • 2017-06-14
    • 1970-01-01
    • 1970-01-01
    • 2010-11-18
    • 1970-01-01
    • 1970-01-01
    • 2012-02-21
    • 2011-06-29
    相关资源
    最近更新 更多