5

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
6

Or

awk '{for (I=1;I<=NF;I++) if ($I == "from") {print $(I+1)};}' file

  • Kindly, how can this command output five words or numbers after "from"? – user88036 May 12 '17 at 0:26
14

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
  • 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? – user1717828 Jun 2 '15 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 Jun 2 '15 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) – Stéphane Chazelas Nov 28 '16 at 9:29
5

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.

  • 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 Aug 15 '17 at 18:47
  • @Kusalananda Honestly, I couldn't figure out a readable solution to do it using just one awk. – Jignesh Darji Aug 15 '17 at 22:52
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 ']'.

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.