Equivalent of grep to awk or sed

awk is superset of grep, so you can use that grep pattern in awk as well:

awk '{match($0, "[^ ]+$"); if (RSTART > 0) print substr($0, RSTART, RLENGTH)}'

in awk:

awk 'NF>0 {print $NF}'     ## fails with end of line spaces; \thnaks{cuonglm}
awk '/[^ ]$/ {print $NF}'  ## fails with tabs in lasts field; \thanks{Terdon}
awk -F ' +'  '$NF {print $NF}'            ## too tricky  
awk 'match($0,/[^ ]+$/,a){print a[0]}'    ## follows def. of grep -o

In sed:

sed -nr 's/(|.* )([^ ]+)$/\2/p'

\thanks{cuonglm}

and (why not?) in Perl

perl -nlE '/([^ ]+)$/ and say $1'

Let's go over what your grep command does first:

  • the -o tells grep to output only the matching part instead of the whole line
  • the -E flag allows use of extended regular expressions
  • '[^ ]+$' will match any non-space character repeated one or more times at the end of the line - basically a word at the end of the line.

Test run:

$ cat input.txt
to be or not to be
that is the question
$ grep -oE '[^ ]+$' input.txt                                      
be
question

Now, how can we do the same in awk ? Well that's easy enough considering that awk operates by default on space-separated entries of each line (we call them words - awk calls them fields). Thus we could print $NF with awk - take the NF variable for number of fields and treat it as referring to specific one. But notice that the grep command would only match non-blank lines, i.e. there is at least one word there. Thus, we need to a condition for awk - operate only on lines which have NF number of fields above zero.

awk 'NF{print $NF}' input.txt

It should be noted that GNU awk at least supports extended regex (I'm not familiar with others as extensively, so won't make claims about others). Thus we could also write a variation on cuonglm's answer:

$ awk '{if(match($0,/[^ ]+$/)) print $NF}' input.txt               
be
question

With GNU sed one can use extended regular expressions as well - that requires -r flag, but you can't simply use same regular expression. There's a need to use backreference with \1.

$ cat input.txt                                                                                                          
to be or not to be
that is the question
blah 

$ sed -r -e 's/^.* ([^ ]+)$/\1/' input.txt                                                                             
be
question
blah

It is possible to obtain desired result with basic regular expression like so:

$ cat input.txt                                                    
to be or not to be
that is the question
blah 
$ sed 's/^.* \([^ ].*\)$/\1/' input.txt                           
be
question
blah 

For more info, please refer to these posts:

  • can we print the last word of each line in linux using sed command?

  • https://unix.stackexchange.com/a/31479/85039

Tags:

Grep

Awk

Sed