9

I have this file

1 deiauk David Smith from California 12 58
2 edvin from Nevada 12 5 8 95 2 48 5
3 jaco My Name Is Jacob I'm from NY 5  6  845 156 585
4 from Miami

And I need to get values after specific word from is it possible to do that in shell? My output should be

California
Nevada
NY
Miami

5 Answers 5

21

Using grep, it can be done as follows:

grep -oP "from\s+\K\w+" input.txt

Here,

-o  ==>  option for printing only the matching part of the line
-P  ==>  use perl-regexp
\K  ==>  do not print that comes before \K (zero-width look-behind assertion)
\w  ==>  match word characters
3
  • Wow, that look behind assertion looks way easier than vim's. Does Perl subscribe to a standard RegEx (if there is such a thing) or is it just a lot easier to understand? Commented Jun 2, 2015 at 22:50
  • 1
    @user1717828 I don't know what RegEx Perl subscribes to, but the cheat-sheet I have with me is based on Perl regex. Moreover, perl regex is more powerful than the basic and extended RegEx.
    – shivams
    Commented Jun 2, 2015 at 22:56
  • @user1717828, that's not a look-behind assertion, it sets the start of the matched portion, so it can replace a look-behind assertion (here the Perl/PCRE look behind assertion would be (?<=from\s+), except that in perl (contrary to vim's \v(from\s+)\@<=) look-behinds can only be of fixed length so wouldn't work) Commented Nov 28, 2016 at 9:29
12

Or:

awk '{for (I=1;I<NF;I++) if ($I == "from") print $(I+1)}' file
1
  • Kindly, how can this command output five words or numbers after "from"?
    – user88036
    Commented May 12, 2017 at 0:26
8

A readable solution would be:

awk -F '${fixed_string}' '{print $2}' file | awk '{print $1}'

What it does:

  • -F '${fixed_string}' separates the input into before and after the given string. So with your file, when we set fixed_string='from', print $2 would give:

    California 12 58 Nevada 12 5 8 95 2 48 5 NY 5 6 845 156 585 Miami

  • Now, all you need is the 1st column of this input. So we pipe the output of the first awk to awk and print the 1st column.

4
  • Could you describe a bit more about what's going on here? Why would ${fixed_string} be a good field separator, for example, and why do you pipe the output of awk through awk again?
    – Kusalananda
    Commented Aug 15, 2017 at 18:47
  • @Kusalananda Honestly, I couldn't figure out a readable solution to do it using just one awk. Commented Aug 15, 2017 at 22:52
  • Point for idea of using the match word as the separator. Easy to remember. @Jignesh Darji I'm not sure what the ${} is for around fixed_string?. Mine worked by simply using awk -F 'from' ... format. Commented Nov 18, 2019 at 10:27
  • awk is awesome, thanks for this simple and easy solution!
    – Kay
    Commented Dec 14, 2021 at 18:56
1

This sed one liner does it:

 sed '/from/s/.*from \([^ ][^ ]*\)[ ]*.*/\1/' input

I'm presuming a space character before the "from" literal string. If you want to have tab-separated fields, you might have to insert a tab-character in all three character-range-match expressions, those between '[' and ']'.

2
  • It will get the last - but it might strip other froms in doing so.
    – mikeserv
    Commented Jun 3, 2015 at 5:10
  • 1
    Just an improvement after removing some redundancies sed 's/.*from \([^ ]*\)[ ]*.*/\1/' input Commented Aug 16, 2017 at 1:06
1

Assume the file name is test.txt

$ cat test.txt
deiauk David Smith from California 12 58
edvin from Nevada 12 5 8 95 2 48 5
jaco My Name Is Jacob I'm from NY 5  6  845 156 585
from Miami

You can use sed to grep everything after from then cut the output like this.

$ cat test.txt | sed 's/.*from //' | cut -d " " -f 1
California
Nevada
NY
Miami

You must log in to answer this question.

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