0

I'd like to get the output of the second command with the 7 character PSI domain (00:01.0) as a variable. How can I write a bash script to do this?

jeff@jeff-probook:/$ lspci | grep VGA
    00:01.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Carrizo (rev c5)
jeff@jeff-probook:/$ lspci -v -s 00:01.0
00:01.0 VGA compatible controller: Advanced Micro Devices, Inc. [AMD/ATI] Carrizo (rev c5) (prog-if 00 [VGA controller])
    Subsystem: Hewlett-Packard Company Carrizo
    Flags: bus master, fast devsel, latency 0, IRQ 231
    Memory at c0000000 (64-bit, prefetchable) [size=256M]
    Memory at d0000000 (64-bit, prefetchable) [size=8M]
    I/O ports at 3000 [size=256]
    Memory at d0d00000 (32-bit, non-prefetchable) [size=256K]
    Expansion ROM at d0800000 [disabled] [size=128K]
    Capabilities: 
    Kernel driver in use: amdgpu
    Kernel modules: amdgpu

This definitely isn't working:

user@host:~$ cat lspciVGA
#!/bin/bash

var1="$(lspci | grep -E "VGA|3D")"
var2="$(expr substr ${var1} 0 7)"
var3="$(sudo lspci -v -s ${var2})"
echo "$var3"

Output:

user@host:~$ bash lspciVGA
expr: syntax error
lspci: option requires an argument -- 's'
Usage: lspci []

Basic display modes:
-mm             Produce machine-readable output (single -m for an obsolete format)
-t              Show bus tree

Display options:
-v              Be verbose (-vv for very verbose)
-k              Show kernel drivers handling each device
-x              Show hex-dump of the standard part of the config space
-xxx            Show hex-dump of the whole config space (dangerous; root only)
-xxxx           Show hex-dump of the 4096-byte extended config space (root only)
-b              Bus-centric view (addresses and IRQ's as seen by the bus)
-D              Always show domain numbers

Resolving of device ID's to names:
-n              Show numeric ID's
-nn             Show both textual and numeric ID's (names & numbers)
-q              Query the PCI ID database for unknown ID's via DNS
-qq             As above, but re-query locally cached entries
-Q              Query the PCI ID database for all ID's via DNS

Selection of devices:
-s [[[[]:]]:][][.[]]   Show only devices in selected slots
-d []:[]                        Show only devices with specified ID's

Other options:
-i        Use specified ID database instead of /usr/share/misc/pci.ids.gz
-p        Look up kernel modules in a given file instead of default modules.pcimap
-M              Enable `bus mapping' mode (dangerous; root only)

PCI access options:
-A      Use the specified PCI access method (see `-A help' for a list)
-O =  Set PCI access parameter (see `-O help' for a list)
-G              Enable PCI access debugging
-H        Use direct hardware access ( = 1 or 2)
-F        Read PCI configuration dump from a given file

Reference: https://stackoverflow.com/questions/8928224/trying-to-retrieve-first-5-characters-from-string-in-bash-error

2 Answers 2

1

there is a problem in the assignment of var2. It should read:

var2=$(expr substr "${var1}" 1 7)

the reason for the quotes is that var1 has whitespaces that confuse substr, and the 0 -> 1 is because it starts counting from 1.

Also there are some problems with your quotes:

#!/bin/bash

var1=$(lspci | grep -E "VGA|3D")
var2=$(expr substr "${var1}" 1 7)
var3=$(sudo lspci -v -s "${var2}")
echo "$var3"
2
  • It worked just updating quotes for second line (var2). Why is that? Can you only use quotes once per line? May 13, 2016 at 20:42
  • if you set var1 to i.e. 'hello world' then the command would become expr substr hello world 1 7 - resulting in error. With quotes 'hello world' is treated as a single argument.
    – user448115
    May 13, 2016 at 20:54
1

Using grep with PCRE (-P):

lspci | grep -Po '^\s*\K\S+(?=\s+VGA\s)'

and

lspci -v -s 00:01.0 | grep -Po '^\s*\K\S+(?=\s+VGA\s)'
  • ^\s* matches zero or more whitespaces at the start and \K discards the match, this is to tackle the second case where there are spaces at the start

  • \S+ matches any number of non-whitespace characters, this is our desired portion

  • The zero width positive lookahead pattern, (?=\s+VGA\s), ensures that the desired match is floowed by VGA after whitespaces after the desired portion.


To save the output in a variable, use command substitution ($()):

value=$(lspci | grep -Po '^\s*\K\S+(?=\s+VGA\s)')

Similarly:

value=$(lspci -v -s 00:01.0 | grep -Po '^\s*\K\S+(?=\s+VGA\s)')

Now you can get the value by $value.


Example (on my system):

$ lspci | grep -Po '^\s*\K\S+(?=\s+VGA\s)'
00:02.0

$ lspci -v -s 00:02.0 | grep -Po '^\s*\K\S+(?=\s+VGA\s)'
00:02.0
2
  • I like how you account for whitespace and view VGA a different way. This worked for me: user@host:~$ cat lspciVGA2 var1=$(lspci | grep -Po '^\s*\K\S+(?=\s+VGA\s)') var2=$(lspci -v -s "${var1}") echo "$var2" May 14, 2016 at 15:15
  • @conman253 Great..
    – heemayl
    May 14, 2016 at 16:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .