5

I want to print the lines that with two columns equal to a variable, for example, input:

2607s1  NC_000067.6 95.92   49  1   1   3   50  1e-14   84.2
2607s1  NC_000067.6 97.73   44  1   0   7   50  4e-14   84.2
2607s1  NC_000067.6 97.67   43  1   0   8   50  1e-13   75.0

and variables for first and last column:

a="2607s1"; b="84.2"

and using awk command, output:

2607s1  NC_000067.6 95.92   49  1   1   3   50  1e-14   84.2
2607s1  NC_000067.6 97.73   44  1   0   7   50  4e-14   84.2

I have tried the following but not work:

awk -v '$1==$a' && '$10==$b' test_file
cat test_file|awk '$1=="($a)" && $10=="($b)"'
cat test_file|awk '$1==($a) && $10==($b)'
cat test_file|awk '$1=="$a" && $10=="$b"'

Moreover, I am running it in a while loop, so the $a and $b keep changing Please help..

Jahid
  • 21,542
  • 10
  • 90
  • 108
once
  • 1,369
  • 4
  • 22
  • 32
  • wrt `I am running it in a while loop` - using a shell loop just to manipulate text is always the wrong approach. The end result is invariably lengthy, awkward, fragile, error prone, slow and generally bad software since that is not what shell is for. You might want to ask for help with that part of the bigger script in a separate question. – Ed Morton Jun 03 '15 at 10:45

3 Answers3

14

You are passing the shell variables to the awk command using a wrong method. It should be like

awk -v a="$a" -v b="$b" '$1==a && $10 == b' 

What it does

  • -v a="$a" creates an awk variable a and assigns the value of shell variable $a to it.

  • -v b="$b" Creates awk variable b.

OR

awk '$1==a && $10 == b' a="$a" b="$b" file

When you write a statement like this

awk -v '$1==$a' && '$10==$b' test_file

awk doesn't know what $a $b is because both are shell variables.

And the correct method of using -v for passing shell variables is as in demonstrated in the examples.

From awk manuals

-v var=val

   --assign var=val

    Assign  the  value  val to the variable var, before execution of
    the program begins.  Such variable values are available  to  the
    BEGIN block of an AWK program.


Test
$ cat file 
2607s1  NC_000067.6 95.92   49  1   1   3   50  1e-14   84.2
2607s1  NC_000067.6 97.73   44  1   0   7   50  4e-14   84.2
2607s1  NC_000067.6 97.67   43  1   0   8   50  1e-13   75.0

$ a="2607s1"; b="84.2"

$ awk -v a="$a" -v b="$b" '$1==a && $10 == b' file 
2607s1  NC_000067.6 95.92   49  1   1   3   50  1e-14   84.2
2607s1  NC_000067.6 97.73   44  1   0   7   50  4e-14   84.2
nu11p01n73R
  • 26,397
  • 3
  • 39
  • 52
  • it works!, is it possible not to use the -v flag in this case? – once Jun 03 '15 at 08:19
  • @once I afraid not :( It is the only method of passing shell variables onto the awk script. – nu11p01n73R Jun 03 '15 at 08:19
  • 1
    It isn't the only way, although it is the best. You can also do `awk '$1==a && $10 == b' a="$a" b="$b" file` – 123 Jun 03 '15 at 08:22
  • @User112638726 Ooch I really missed that. Will add to answer. Thank you – nu11p01n73R Jun 03 '15 at 08:24
  • Yeah there is another method as well. I missed it in the first place. see the updated answer or comment by @User112638726 – nu11p01n73R Jun 03 '15 at 08:27
  • You can also use `ENVIRON["a"]` but again `-v` is usually the right approach. See http://cfajohnson.com/shell/cus-faq-2.html#Q24. I personally find `"a=$a"` a very odd-looking syntax vs `a="$a"` but I expect it will work. – Ed Morton Jun 03 '15 at 10:40
4

You can also do this (this avoids using -v parameters)

awk '$1=="'$a'" && $10=="'$b'"' file

The quote ' just before $a will turn off string interpretation.

The quote ' just after $a will turn on string interpretation.

$a is in this way interpreted and replaced by its value.

RémiH
  • 41
  • 2
1

You may try the below awk command.

awk -v var1="$a" -v var2="$b" '$1==var1&&$NF==var2' file
Avinash Raj
  • 172,303
  • 28
  • 230
  • 274