0

hg tags output on terminal:

tip                              596:bb834c42599f
P_SONY_1004.21.15                595:db10157b1515
P_PHILIPS_1000.21.2              590:67b7e71f76b4
P_SONY_1004.21.2                 539:2b50e157e217
P_SONY_10015.21.2                533:15160fyafd88
P_creative.21.1                  512:cdac14a00df4
P_SONY_1004.15.5                 500:21affdf1bbfd
P_SONY_1002.15.5                 466:a7bad21505ca
P_SONY_1002.15.15                424:efbe741500bb
P_creative.15.2                  420:415c415a65fa
P_SONY_1004.15.1                 414:24f1ab415c15
P_PHILIPS_1000.15.1              412:5d151556c288
P_SONY_1002.15.1                 410:bf1f5af64ebb
P_SONY_1002.15.1                 390:152e0f4ec815
P_creative.8.2                   370:ecdc64f8a4b4
P_creative.8.1                   350:5b8e81bd725a
P_creative.7.5                   343:221d5c15efa6
P_creative.6.1                   222:62115db1e015

from this output i have to extract 2nd line from lines containing "creative" word

I tried this:

hg tags | awk '/creative/{print $1;}'

Its output:

P_creative.21.1
P_creative.15.2
P_creative.8.2
P_creative.8.1
P_creative.7.5
P_creative.6.1

But i want only this as output: P_creative.15.2

How can i change my command to get "P_creative.15.2" as output and how can i use it in shell script?

also can i extract "15.2" from it ?

Patrick
  • 2,464
  • 3
  • 30
  • 47

5 Answers5

7

You can c as you like to get cth match :

awk -v c=2 '/creative/{count++;}count==c{print $0;exit}' file

(The above will print the whole line)

To get first word:

awk -v c=2 '/creative/{count++;}count==c{print $1;exit}' file
P.P
  • 117,907
  • 20
  • 175
  • 238
  • Much better than my own. – mhawke May 30 '14 at 07:10
  • @Blue Moon - it gives "P_creative.15.2 420:415c415a65fa" as ouput, i want only "P_creative.15.2" – Patrick May 30 '14 at 07:17
  • You can print `$1` instead of `$0`. Edited my answer. `$0` is for the whole line; `$1` is the first word, `$2` is the 2nd word & so on. If you want to match using a different delimiter, you can do so using `-F`. – P.P May 30 '14 at 07:18
  • @BlueMoon and how to extract only number(15.2) from this – Patrick May 30 '14 at 07:25
  • @Patrick `awk -F'.' -v c=2 '/creative/{count++;}count==c{print $2;exit}' file` will do for your sample input. If the format of your input changes, you may need change the field you print or delimiter accordingly. – P.P May 30 '14 at 07:29
  • @BlueMoon it gives 15 only i want 15.2 – Patrick May 30 '14 at 07:34
  • @Patrick `awk -F'[. ]' -v c=2 '/creative/{count++;}count==c{print $2"."$3;exit}' file` will give 15.2 – P.P May 30 '14 at 07:39
  • @Patrick Do `VERSION=$(awk -F'[. ]' -v c=2 '/creative/{count++;}count==c{print $2"."$3;exit}' file); echo $VERSION` – P.P May 30 '14 at 09:05
  • A little more concise: `awk -v c=2 '/creative/ && ++count==c {print $1;exit}' file` – glenn jackman May 30 '14 at 10:24
  • @BlueMoon how can i replace "creative" with environment variable, i tried this: $BRANCH="creative" VERSION=$(awk -F'[. ]' -v c=2 '/$BRANCH/{count++;}count==c{print $2"."$3;exit}' file); – Patrick May 30 '14 at 14:44
  • @Patrick Yes. You'll have to pass that variable to `awk` and you shouldn't have `$` when assigning a variable: `BRANCH="creative"; awk -F'[. ]' -v c=2 -v BRANCH=${BRANCH} '$0 ~ BRANCH{count++;}count==c{print $2"."$3;exit}' f` – P.P May 30 '14 at 14:56
  • @BlueMoon ur code not working – Patrick May 30 '14 at 15:02
  • @Patrick I tested it and it works. What problem you see? Do you have code exactly I have said in the comment? – P.P May 30 '14 at 15:22
  • @BlueMoon yes its working – Patrick Jun 01 '14 at 17:48
3

Like this:

awk '/creative/{if(++p==2){gsub(/.*creative./,"");print $1;exit}}' f

To assign the result to a variable, use this $()

VERSION=$(awk '/creative/{if(++p==2){gsub(/.*creative./,"");print $1;exit}}' f)
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
2

For the second instance:

hg tags | awk '/creative/{print $1;}' | head -2 | tail -1

More generally, where $n identifies the required instance:

n=2
hg tags | awk '/creative/{print $1;}' | head -$n | tail -1
mhawke
  • 84,695
  • 9
  • 117
  • 138
  • Not so good. Go for one of the "all awk" answers. – mhawke May 30 '14 at 07:14
  • how to write this in shell script – Patrick Jun 16 '14 at 12:13
  • @Patrick : Put the commands in a file and add `#!/usr/bin/env sh` as the first line. Make the file executable. If you need the functionality in multiple places in your shell script, put it in a function. There are plenty of tutorials - the first google result for "sh scripting" led me here: http://www.freeos.com/guides/lsst/ch02sec01.html – mhawke Jun 16 '14 at 12:44
  • how can i replace creative with a variable, so that my code will work generic – Patrick Jun 16 '14 at 13:25
  • You need to use double quotes for the awk script so that shell variables are expanded, and escape the `$` in `print $1`. Change command to `hg tags | awk "/$PATTERN/{print \$1;}" | head -$n | tail -1`. Setting `PATTERN=creative`will result in the same behaviour. – mhawke Jun 16 '14 at 13:33
1

This might work for you (GNU sed):

sed -n '/creative/{x;/./{x;p;q};x;H}' file

Use the hold space as a flag. Can be adapted:

sed -nr '/creative/{H;x;/^(\n[^\n]*){5}/{x;p;q};x}' file

Finds the 5th such line.

potong
  • 55,640
  • 6
  • 51
  • 83
1

Another way:

awk '/creative/{print $1;}' yourfile | sed -n '2p'

To get only version:

awk '/creative/{print $1;}' yourfile | sed -n '2s/[^.]*\.\(.*\)/\1/p'

Test:

$ awk '/creative/{print $1;}' file | sed -n '2p'
P_creative.15.2
$ awk '/creative/{print $1;}' file | sed -n '2s/[^.]*\.\(.*\)/\1/p'
15.2
sat
  • 14,589
  • 7
  • 46
  • 65