How to insert shell variable inside awk command

11,604

Solution 1

If you want to /grep/ with your variable, you have 2 choices :

interface=eth0
awk "/$interface/{print}"

or

awk -v interface=eth0 '$0 ~ interface{print}'

See http://www.gnu.org/software/gawk/manual/gawk.html#Using-Shell-Variables

Solution 2

it's like I thought, awk substitutes variables properly, but between //, inside regex ( or awk regex, depending on some awk parameter AFAIR), awk variable cannot be used for substitution

I had no issue grepping with variable inside an awk program (for simple regexp cases):

sawk1='repo\s+module2' 
sawk2='@project2\s+=\s+module2$'
awk "/${sawk1}/,/${sawk2}/"'{print}' aFile

(Here the /xxx/,/yyy/ displays everything between xxx and yyy)
(Note the double-quoted "/${sawk1}/,/${sawk2}/", followed by the single-quoted '{print}')

This works just fine, and comes from "awk: Using Shell Variables in Programs":

A common method is to use shell quoting to substitute the variable’s value into the program inside the script.
For example, consider the following program:

printf "Enter search pattern: "
read pattern
awk "/$pattern/ "'{ nmatches++ }
     END { print nmatches, "found" }' /path/to/data

The awk program consists of two pieces of quoted text that are concatenated together to form the program.

  • The first part is double-quoted, which allows substitution of the pattern shell variable inside the quotes.
  • The second part is single-quoted.

It does add the caveat though:

Variable substitution via quoting works, but can potentially be messy.
It requires a good understanding of the shell’s quoting rules (see Quoting), and it’s often difficult to correctly match up the quotes when reading the program.

Share:
11,604
Rafael Adel
Author by

Rafael Adel

About me

Updated on June 04, 2022

Comments

  • Rafael Adel
    Rafael Adel almost 2 years

    I'm trying to write a script, In this script i'm passing a shell variable into an awk command, But when i run it nothing happens, i tried to run that line only in the shell, i found that no variable expansion happened like i expected. Here's the code :

      1 #!/bin/bash
      2 
      3 # Created By Rafael Adel
      4 
      5 # This script is to start dwm with customizations needed
      6 
      7 
      8 while true;do
      9         datestr=`date +"%r %d/%m/%Y"`
     10         batterystr=`acpi | grep -oP "([a-zA-Z]*), ([0-9]*)%"`
     11         batterystate=`echo $batterystr | grep -oP "[a-zA-Z]*"`
     12         batterypercent=`echo $batterystr | grep -oP "[0-9]*"`
     13 
     14         for nic in `ls /sys/class/net`
     15         do
     16                 if [ -e "/sys/class/net/${nic}/operstate" ]
     17                 then
     18                         NicUp=`cat /sys/class/net/${nic}/operstate`
     19                         if [ "$NicUp" ==  "up" ]
     20                         then
     21                                 netstr=`ifstat | awk -v interface=${nic} '$1 ~ /interface/ {printf("D: %2.1fKiB, U: %2.1fKiB",$6/1000, $8/1000)}'`
     22                                 break
     23                         fi
     24                 fi
     25         done
     26 
     27 
     28         finalstr="$netstr | $batterystr | $datestr"
     29 
     30         xsetroot -name "$finalstr"
     31         sleep 1
     32 done &
     33 
     34 xbindkeys -f /etc/xbindkeysrc
     35 
     36 numlockx on
     37 
     38 exec dwm
    

    This line :

    netstr=`ifstat | awk -v interface=${nic} '$1 ~ /interface/ {printf("D: %2.1fKiB, U: %2.1fKiB",$6/1000, $8/1000)}'`
    

    Is what causes netstr variable not to get assigned at all. That's because interface is not replaced with ${nic} i guess.

    So could you tell me what's wrong here? Thanks.