2

I am executing the command

lsof -nPs

The output of the command:

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

Is there a way to put a dummy value to the values of field if it is empty?

for ex:

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

Note:

  • the main issue is the TID field, it appears in CentOs 7, but doesn't in Centos 6.
  • I am making a script that would work on both the Os. (CentOs 6 and CentOs 7)
  • What I want to achieve is, Whenever TID appears in the output, just ignore it.
  • What I thought would work to achieve the goal is, I check the number of fields in output (using NF of awk), and check if number of fields is 10 => ignore TID.
  • Why it did not work? : There might be the case where the value of SIZE and DEVICE is empty. in that case, the number of the fields will be less than 10 and hence the script would not be able to handle the scenario when TID is non-empty. so, it would not be able to ignore it.

So, If there is a way to put dummy value to empty fields, it would solve the issue.

Is there a way to put a dummy token if the value is empty.? like null, so I could check and ignore if the value is null.

Any other solution to this would be a great help.

Thank you.

Jay Joshi
  • 1,402
  • 1
  • 13
  • 32

1 Answers1

0

This (using GNU awk for FIELDWIDTHS) converts your file from fixed-width-fields to tab-separated values so you don't actually need to set any empty fields to a string of "null" to be able to recognize empty fields for any further processing (e.g. importing into an Excel spreadsheet or parsing with subsequent scripts that use tab-separated fields):

$ 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

If you really do feel like you'd want to have "null" values and fields padded with blanks then it's just a tiny tweak to set $i if its empty and pass the output to column to do the formatting (or you can format it within awk if you like):

$ 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

or to keep exactly the original white space and field alignment:

$ 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

If you don't have GNU awk for FIELDWIDTHS you can do the same in any awk with a loop calling substr().

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • Thank you for the answer @Ed, however, the field's width is not fixed. It changes according to the values. For example, if the User's value is something long instead of "root", the width of the field USER will increase accordingly. (18 when I was testing.) so in that case, the awk snippet fails. Can you please suggest a solution to this problem.? – Jay Joshi Apr 23 '18 at 07:16