Skip to content

Instantly share code, notes, and snippets.

@rcanepa
Last active August 10, 2016 19:51
Show Gist options
  • Save rcanepa/01a0a01bc4287b990e3efccc80da2287 to your computer and use it in GitHub Desktop.
Save rcanepa/01a0a01bc4287b990e3efccc80da2287 to your computer and use it in GitHub Desktop.
UNIX awk

#awk In awk, a file is treated as a sequence of records, and by default each line is a record and every word is a field.

$ cat text
this is the first line
second one
third one
who cares anymore?
....

$ awk '{print $1}' text
               ^
     print the first field of every record

this
second
third
who
....
$ awk '{print $1 $2}' text
               ^  ^
         print field 1 and 2
thisis
secondone
thirdone
whocares
....
$ awk '{print $1, $2}' text
                ^
         the comma acts as a space
this is
second one
third one
who cares
....

###Using patterns

$ awk '/who/' text
       ^   ^
   this would return all lines containing the word 'who'

who cares anymore?
$ awk '/e$/' text
         ^
     return all lines that ends in an 'e'
       
this is the first line
second one
third one
$ awk '/[a-z]/' text
          ^
    return lines that contain lowercase letters

this is the first line
second one
third one
who cares anymore?
$ awk '/d+ / text
        ^ ^
  return all lines that contain one or more letters 'd' followed by a space

second one
third one
$ awk '/\.+|^t/' text
         ^   ^
   all lines that contain one or more dots or start with a 't'

this is the first line
third one
....

###awk variables

FS: input field separator value

OFS: output field separator value

NF: number of fields on the current line

NR: number of record in the current file

RS: record separator value

ORS: output record separator

FILENAME: current file name being processed

$ awk '{print NR}' text
1
2
3
4
5
$ awk 'END{print NR}' text
        ^
  END indicates that the next statement should be executed one awk 
  has finish processing the whole file
5
$ awk 'END{print $1}' text
        ^         ^
    print the first word of the last line
....
$ awk 'BEGIN{print "STARTING..."};{print NR, $1};END{print "WORK COMPLETED..."}' text
        ^                         
    BEGIN indicates that the next statement should be executed 
    before the file is processed
STARTING...
1 this
2 second
3 third
4 who
5 ....
WORK COMPLETED...
$ awk '{if(NR~/^2/)print}' text
             ^
      ~ indicates a regular expression match (this would return 
      lines number 2, 21, 22, 23 ...)
second one
$ awk '{if(NR!~/^2/)print}' text
           ^
   !~ negates the match (this would return lines
   number 1, 3, 4, 5, ..., 19, 30, 31 ...
this is the first line
third one
who cares anymore?
....
$ awk '{if(NR%2==0)print}' text
             ^ ^
     return even number lines (2, 4, 6 ...)
second one
who cares anymore?

###Using pipe to pass information to awk

$ ls *.sh
$ ls | awk '/\.sh$/'
              ^
      filter files that end in '.sh'
pia_upscript.sh
$ ls | awk '/^pia_[a-z]+$/'
                ^ ^   ^   ^
    files that start with 'pia_' and then continue
    and end with one or more lower case letters
pia_psid
pia_route
$ ls | awk '/[.](err|out|sh)$/'
              ^   ^   ^   ^ ^
      files terminated by '.err', '.out' or '.sh'

AlTest1.err
AlTest1.out
pia_upscript.sh
$ ifconfig en0 | awk '{if(NR==4)print $2}'
192.168.1.102

$ echo 'http://192.168.0.1' | awk 'BEGIN{FS="//"}{print $2}'
                                              ^
                                    replace the field (word) separator by //
                                    and print the second field
192.168.0.1
$ man awk | awk 'BEGIN{var=0};{if(/print/){var++}};END{print var};'
                        ^           ^       ^                 ^
        count the number of times that the word 'print' is found in the 
        awk man pages
10
$ cat numbers
Renzo 90 48 68 29 100
Marleen 29 49 87 90 77
Karl 83 84 10 40 90
Celine 100 89 20 100 78
$ cat numbers | awk 'BEGIN{print "Averages";print "----------";total=0};{var=0};{var=($2+$3+$4+$5+$6)/5};{total+=var};{print $1, var};END{print "----------";print "AVG:", total/NR}'
                      ^1                                                  ^2                ^3              ^4            ^5            ^6                                    ^7   
^1 before processing the file's lines, set variable total to 0 and print a message
LOOP
^2 for every line, set variable var to 0
^3 sum line's numbers, divide them by 5 and then assign that value to var
^4 increase variable total by variable val's value
^5 print the first word of the line followed by the variable var's value
END
^6 after processing all lines, print a message
^7 print the value of variable total divided by the number of lines processed

Averages
----------
Renzo 67
Marleen 66.4
Karl 61.4
Celine 77.4
----------
AVG: 68.05

###Executing system calls

$ echo "js .sh" | awk '{if($2==".sh"){system("ls | grep " $2 "$")}}'
                                 ^                         ^
                 if the second word of the line is equal to '.sh', then
                 execute ls | grep '.sh$'
pia_upscript.sh 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment