gkr2d2
gkr2d2

Reputation: 773

Search for string in a file from a certain line no

How to search for a string from/after certain line in text file using bash script?

E.g. I want to search for first occurrence of "version:" string but not at start of file but at line no. say 35 which contains text *-disk:0 so that I would get product name of disk-0 only and nothing else. My current approach is as follows where line_no was line no. of the line where disk:0 is present. But sometimes there is vendor name also present in-between the disk:0 and version. At that time, this logic fails.

ver_line_no=$(echo $(( line_no + 6 )))
ver_line_text=`sed -n ${ver_line_no}p $1`
check_if_present=`echo $fver_line_text | grep "version:"`

Background: I am trying to parse output of lshw commmand.

*-disk:0
       description: ATA Disk
       product: SAMSUNG 
       physical id: 0
       bus info: scsi@z:y:z:0
       logical name: /dev/sda 
       version: abc
       serial: pqr
       size: 2048GiB 
       capabilities: axy, pqr
       configuration: pqr, abc, ghj
  *-disk:1
       description: ATA Disk
       product: TOSHIBA
       physical id: 0
       bus info: scsi@p:q:z:0
       logical name: /dev/sdb 
       version: nmh
       serial: pqasd
       size: 2048GiB  
       capabilities: axy, pqr
       configuration: pqr, abc, ghj

This is the sample information. I want to print information in tabular format using bash script.

Upvotes: 0

Views: 460

Answers (5)

ISQ
ISQ

Reputation: 2893

A general solution using awk (assuming that every disk has a version).

File 'find_disk_version.awk'

/disk:/ {
    disk_found="true"
    disk_name=$1
}

/version:/ {
    if (disk_found) {
       print disk_name" "$2
       disk_found=""
   }
}

Test file 'test':


Something_else
       version: ver_something_else
       serial: blabla
       configuration: foo, bar
*-disk:0
       description: ATA Disk
       version: ver.0
       serial: pqr
*-disk:1
       version: ver1
       serial: pqasd
       configuration: pqr, abc, ghj
Something_else_again
       version: ver_somethingelse_again
       serial: foobar
       configuration: bar, foo
*-disk:2
       version: ver2
       serial: pqasd
       configuration: pqr, abc, ghj


Output:


$ cat test | awk -f find_disk_version.awk
*-disk:0 ver.0
*-disk:1 ver1
*-disk:2 ver2

Instead of 'cat test' can be your command 'lshw'

P.S. the script will not work if there is a disk without version.

Upvotes: 0

Anubis
Anubis

Reputation: 7445

sed solution:

If you want to search for first occurrence after given line number (e.g. 10).

l=10
lshw | sed -n "${l},$ {/version/{p;q}}"

If you want to search for first occurrence after given line content (e.g. *-disk:0)

lshw | sed -n '/*-disk:0/,${/version/{p;q}}'

Upvotes: 1

KamilCuk
KamilCuk

Reputation: 142005

You need to print all lines up the end. The $ represents the end in sed.

sed -p '6,$p'

Will print lines from 6th line to the end. Be aware of quoting, so that $ doesn't get expanded.

You want:

ver_line_no=$(( line_no + 6 ))
ver_line_text=$(sed -n "${ver_line_no}"',$p' "$1")
check_if_present=$(echo "$fver_line_text" | grep "version:")

Notes:

  • Backticks ` are deprecated. Use $( ...) command substitution instead.
  • Always quote your variables.
  • Doing echo $(( .. )) is just repeating yourself. Just $(( ... )).
  • Sometimes on systems without sed you can use cut -d $'\n' -f6-.

Upvotes: 0

Jack
Jack

Reputation: 6198

You should be able to cut out the block you want with sed, then use grep:

sudo lshw | sed -n '/\*-disk:0/,/\s*\*/p' | grep 'version:'

The sed command does not print any lines (-n), then finds the block between *-disk:0 and the next * and prints only that (p).

Upvotes: 1

anubhava
anubhava

Reputation: 786289

You may use this awk that searches for *-disk:0 in a file to toggle a flag to true:

awk -F: '$1 ~ /\*-disk$/{p = ($2 == 0)} p && /^[[:blank:]]*version:/' file

   version: abc

Upvotes: 0

Related Questions