Reading a file line by line and print required lines based on pattern

Hi All,

i want to write a shell script read below file line by line and want to exclude the lines which contains empty value for MOUNTPOINT field.

i am using centos 7 Operating system.

want to read below file.

[root@matilda final]# cat /tmp/d5
NAME="/dev/sda" TYPE="disk" SIZE="60G" OWNER="root" GROUP="disk" MODE="brw-rw----" PKNAME="" MOUNTPOINT=""
NAME="/dev/sda1" TYPE="part" SIZE="500M" OWNER="root" GROUP="disk" MODE="brw-rw----" PKNAME="/dev/sda" MOUNTPOINT="/boot"
NAME="/dev/sda2" TYPE="part" SIZE="29.5G" OWNER="root" GROUP="disk" MODE="brw-rw----" PKNAME="/dev/sda" MOUNTPOINT=""
NAME="/dev/mapper/centos-root" TYPE="lvm" SIZE="56.5G" OWNER="root" GROUP="disk" MODE="brw-rw----" PKNAME="/dev/sda2" MOUNTPOINT="/"
NAME="/dev/mapper/centos-swap" TYPE="lvm" SIZE="3G" OWNER="root" GROUP="disk" MODE="brw-rw----" PKNAME="/dev/sda2" MOUNTPOINT="[SWAP]"
NAME="/dev/sda3" TYPE="part" SIZE="30G" OWNER="root" GROUP="disk" MODE="brw-rw----" PKNAME="/dev/sda" MOUNTPOINT=""
NAME="/dev/mapper/centos-root" TYPE="lvm" SIZE="56.5G" OWNER="root" GROUP="disk" MODE="brw-rw----" PKNAME="/dev/sda3" MOUNTPOINT="/"
NAME="/dev/sr0" TYPE="rom" SIZE="603M" OWNER="root" GROUP="cdrom" MODE="brw-rw----" PKNAME="" MOUNTPOINT=""

Desired output :

Mountpoint:"/boot"
 Type:"part"

Mountpoint:"/"
 Type:"lvm"
Mountpoint:"[SWAP]"
 Type:"lvm"

Mountpoint:"/"
 Type:"lvm"

i am using below shell script , but i am unable to ignore the lines which contains Mountpoint value is empty.

My Script :

#!/bin/bash
FILE=/tmp/d5
while read LINE; do
mountpoint=$(echo "$LINE" | awk -F " " '{print$8}'|awk -F "=" '{print$2}')

disk=$(echo "$LINE" | awk -F " " '{print$1}'|awk -F "=" '{print$2}')
Type=$(echo "$LINE" | awk -F " " '{print$2}'|awk -F "=" '{print$2}')

if [ "$mountpoint" != "" ];then

      echo -e "Mountpoint:$mountpoint \n Type:$Type"

fi
done < $FILE

i am getting below output ;

Mountpoint:""
 Type:"disk"
Mountpoint:"/boot"
 Type:"part"
Mountpoint:""
 Type:"part"
Mountpoint:"/"
 Type:"lvm"
Mountpoint:"[SWAP]"
 Type:"lvm"
Mountpoint:""
 Type:"part"
Mountpoint:"/"
 Type:"lvm"
Mountpoint:""
 Type:"rom"

Can someone please help me on this issue.

That mountpoint variable is not empty but holds "" . Change the if test to

if [ "$mountpoint" != \"\" ];

and it will fly...

EDIT: BTW, running awk 6 times per line to extract some variables is not the most efficient way to go. The read builtin command can split a line to be read into variables, like

read NAME TYPE SIZE OWNER GROUP MODE PKNAME MOUNTPOINT

, which will fill all those variables, given the input file is consistently well behaved. Get rid of the prefixes before the equals signs with shell "parameter expansion".
Or, adjust IFS and read the values immediately:

IFS="$IFS="
read _ NAME _ TYPE _ SIZE _ OWNER _ GROUP _ MODE _ PKNAME _ MOUNTPOINT

The _ is a dummy variable to be discarded.
With a file structure as presented, and using a recent bash with "process substitution", you could do even

while read LINE
  do    . <(echo $LINE)
        if [ "$MOUNTPOINT" ]
          then  echo -e "Mountpoint:$MOUNTPOINT \n Type:$TYPE"
        fi
  done < $FILE
Mountpoint:/boot 
 Type:part
Mountpoint:/ 
 Type:lvm
Mountpoint:[SWAP] 
 Type:lvm
Mountpoint:/ 
 Type:lvm

, i.e source each line to have it assign all the variables miraculously automatically...

2 Likes

I wonder if . <(echo $LINE) does the same as eval $LINE .?

In fact I get a different (wrong) result in bash-3 for
. <(echo $LINE
and identical (correct) results in all shells for
. <(echo "$LINE"
eval $LINE
eval "$LINE"

Thanks all for sharing the information.

now i am able to get the required output.
Output :

mounted:"/boot" type:"part" file_system:"/dev/sda1"

mounted:"/" type:"lvm" file_system:"/dev/mapper/centos-root"

mounted:"[SWAP]" type:"lvm" file_system:"/dev/mapper/centos-swap"

mounted:"/" type:"lvm" file_system:"/dev/mapper/centos-root"

below is my df -h output
which is stored in
FILE1=/tmp/d4 file as below

Filesystem Size Used Avail Use% Mounted on
devtmpfs 1.9G 0 1.9G 0% /dev
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 1.9G 176M 1.7G 10% /run
tmpfs 1.9G 0 1.9G 0% /sys/fs/cgroup
/dev/mapper/centos-root 57G 48G 9.3G 84% /
/dev/sda1 497M 217M 281M 44% /boot
tmpfs 379M 0 379M 0% /run/user/0

simultaneously i want to read another file which contains df -h ouput. and want to compare the Filesystem field with $NAME field in above ouput
if both are same then i want to add remaining fields of df -h output to current ouput

Example :
if file_system:"/dev/mapper/centos-root" is equal to df -h ouput "/dev/mapper/centos-root"

then for the current ouput
mounted:"/" type:"lvm" file_system:"/dev/mapper/centos-root" i want to add remaining df -h field output.

desired output :
mounted:"/" type:"lvm" file_system:"/dev/mapper/centos-root" Avail:"9.3G " Use%:"84%"

used below script :

#!/bin/bash
FILE=/tmp/d5
FILE1=/tmp/d4
while read LINE;
do . <(echo $LINE)
if [ "$MOUNTPOINT" != "" ]

mounted=$MOUNTPOINT

file_system=$NAME
type=$TYPE

while read LINE1;
do . <(echo $LINE1)

File_System=$Filesystem
if [ "$MOUNTPOINT" == "$Filesystem" ];then

echo -e "mounted:$MOUNTPOINT type:$type file_system:$Filesystem avail:$Avail \n"

done < FILE1

fi
fi
done < $FILE

./zzz: line 22: syntax error near unexpected token `done'
./zzz: line 22: `done < FILE1'