How do I use shell variables in an awk script?












216















I found some ways to pass external shell variables to an awk script, but I'm confused about ' and ".



First, I tried with a shell script:



$ v=123test
$ echo $v
123test
$ echo "$v"
123test


Then tried awk:



$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123


Why is the difference?



Lastly I tried this:



$ awk 'BEGIN{print " '$v' "}'
$ 123test
$ awk 'BEGIN{print ' "$v" '}'
awk: cmd. line:1: BEGIN{print
awk: cmd. line:1: ^ unexpected newline or end of string


I'm confused about this.










share|improve this question




















  • 1





    I like the -v as shown below, but this is really a great exercise in thinking about how to protect things from the shell. Working through this, my first cut use backslashes on spaces and dollar signs. Needless to say the examples here were well worth my time.

    – Chris
    Dec 20 '16 at 21:00











  • Related: Difference between single and double quotes in awk.

    – codeforester
    May 11 '18 at 18:45
















216















I found some ways to pass external shell variables to an awk script, but I'm confused about ' and ".



First, I tried with a shell script:



$ v=123test
$ echo $v
123test
$ echo "$v"
123test


Then tried awk:



$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123


Why is the difference?



Lastly I tried this:



$ awk 'BEGIN{print " '$v' "}'
$ 123test
$ awk 'BEGIN{print ' "$v" '}'
awk: cmd. line:1: BEGIN{print
awk: cmd. line:1: ^ unexpected newline or end of string


I'm confused about this.










share|improve this question




















  • 1





    I like the -v as shown below, but this is really a great exercise in thinking about how to protect things from the shell. Working through this, my first cut use backslashes on spaces and dollar signs. Needless to say the examples here were well worth my time.

    – Chris
    Dec 20 '16 at 21:00











  • Related: Difference between single and double quotes in awk.

    – codeforester
    May 11 '18 at 18:45














216












216








216


65






I found some ways to pass external shell variables to an awk script, but I'm confused about ' and ".



First, I tried with a shell script:



$ v=123test
$ echo $v
123test
$ echo "$v"
123test


Then tried awk:



$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123


Why is the difference?



Lastly I tried this:



$ awk 'BEGIN{print " '$v' "}'
$ 123test
$ awk 'BEGIN{print ' "$v" '}'
awk: cmd. line:1: BEGIN{print
awk: cmd. line:1: ^ unexpected newline or end of string


I'm confused about this.










share|improve this question
















I found some ways to pass external shell variables to an awk script, but I'm confused about ' and ".



First, I tried with a shell script:



$ v=123test
$ echo $v
123test
$ echo "$v"
123test


Then tried awk:



$ awk 'BEGIN{print "'$v'"}'
$ 123test
$ awk 'BEGIN{print '"$v"'}'
$ 123


Why is the difference?



Lastly I tried this:



$ awk 'BEGIN{print " '$v' "}'
$ 123test
$ awk 'BEGIN{print ' "$v" '}'
awk: cmd. line:1: BEGIN{print
awk: cmd. line:1: ^ unexpected newline or end of string


I'm confused about this.







bash shell awk






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Sep 3 '18 at 19:41









codeforester

18.7k84267




18.7k84267










asked Sep 29 '13 at 7:45









hqjmahqjma

1,083285




1,083285








  • 1





    I like the -v as shown below, but this is really a great exercise in thinking about how to protect things from the shell. Working through this, my first cut use backslashes on spaces and dollar signs. Needless to say the examples here were well worth my time.

    – Chris
    Dec 20 '16 at 21:00











  • Related: Difference between single and double quotes in awk.

    – codeforester
    May 11 '18 at 18:45














  • 1





    I like the -v as shown below, but this is really a great exercise in thinking about how to protect things from the shell. Working through this, my first cut use backslashes on spaces and dollar signs. Needless to say the examples here were well worth my time.

    – Chris
    Dec 20 '16 at 21:00











  • Related: Difference between single and double quotes in awk.

    – codeforester
    May 11 '18 at 18:45








1




1





I like the -v as shown below, but this is really a great exercise in thinking about how to protect things from the shell. Working through this, my first cut use backslashes on spaces and dollar signs. Needless to say the examples here were well worth my time.

– Chris
Dec 20 '16 at 21:00





I like the -v as shown below, but this is really a great exercise in thinking about how to protect things from the shell. Working through this, my first cut use backslashes on spaces and dollar signs. Needless to say the examples here were well worth my time.

– Chris
Dec 20 '16 at 21:00













Related: Difference between single and double quotes in awk.

– codeforester
May 11 '18 at 18:45





Related: Difference between single and double quotes in awk.

– codeforester
May 11 '18 at 18:45












8 Answers
8






active

oldest

votes


















374














Getting shell variables into awk



may be done in several ways. Some are better than others. This should cover most of them. If you have a comment, please leave below.





Using -v (The best way, most portable)



Use the -v option: (P.S. use a space after -v or it will be less portable. E.g., awk -v var= not awk -vvar=)



variable="line onenline two"
awk -v var="$variable" 'BEGIN {print var}'
line one
line two


This should be compatible with most awk, and the variable is available in the BEGIN block as well:



If you have multiple variables:



awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'


Warning. As Ed Morton writes, escape sequences will be interpreted so t becomes a real tab and not t if that is what you search for. Can be solved by using ENVIRON or access it via ARGV





Variable after code block



Here we get the variable after the awk code. This will work fine as long as you do not need the variable in the BEGIN block:



variable="line onenline two"
echo "input data" | awk '{print var}' var="${variable}"
or
awk '{print var}' var="${variable}" file


This also works with multiple variables
awk '{print a,b,$0}' a="$var1" b="$var2" file



Using variable this way does not work in BEGIN block:



echo "input data" | awk 'BEGIN {print var}' var="${variable}"




Here-string



Variable can also be added to awk using a here-string from shells that support them (including Bash):



awk '{print $0}' <<< "$variable"
test


This is the same as:



printf '%s' "$variable" | awk '{print $0}'


P.S. this treats the variable as a file input.






ENVIRON input



As TrueY writes, you can use the ENVIRON to print Environment Variables.
Setting a variable before running AWK, you can print it out like this:



X=MyVar awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
MyVar /bin/bash





ARGV input



As Steven Penny writes, you can use ARGV to get the data into awk:



v="my data"
awk 'BEGIN {print ARGV[1]}' "$v"
my data


To get the data into the code itself, not just the BEGIN:



v="my data"
echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"
my data test




Variable within the code: USE WITH CAUTION



You can use a variable within the awk code, but it's messy and hard to read, and as Charles Duffy points out, this version may also be a victim of code injection. If someone adds bad stuff to the variable, it will be executed as part of the awk code.



This works by extracting the variable within the code, so it becomes a part of it.



If you want to make an awk that changes dynamically with use of variables, you can do it this way, but DO NOT use it for normal variables.



variable="line onenline two"
awk 'BEGIN {print "'"$variable"'"}'
line one
line two


Here is an example of code injection:



variable='line onenline two" ; for (i=1;i<=1000;++i) print i"'
awk 'BEGIN {print "'"$variable"'"}'
line one
line two
1
2
3
.
.
1000


You can add lots of commands to awk this way. Even make it crash with non valid commands.





Extra info:



Use of double quote



It's always good to double quote variable "$variable"

If not, multiple lines will be added as a long single line.



Example:



var="Line one
This is line two"

echo $var
Line one This is line two

echo "$var"
Line one
This is line two


Other errors you can get without double quote:



variable="line onenline two"
awk -v var=$variable 'BEGIN {print var}'
awk: cmd. line:1: onenline
awk: cmd. line:1: ^ backslash not last character on line
awk: cmd. line:1: onenline
awk: cmd. line:1: ^ syntax error


And with single quote, it does not expand the value of the variable:



awk -v var='$variable' 'BEGIN {print var}'
$variable


More info about AWK and variables



Read this faq.






share|improve this answer





















  • 1





    "messy and hard to read" ignores the more important security concern of code injection when directly substituting strings into awk code.

    – Charles Duffy
    Feb 18 '16 at 20:21






  • 1





    @CharlesDuffy. You are 100% correct. Cleaned up some more.

    – Jotne
    Feb 18 '16 at 21:07






  • 1





    @EdMorton. Thanks for the input. I am on different planet compare to you about this :) Most of this post are made and change due to comments by others. Updated post to reflect your comments.

    – Jotne
    Feb 16 at 7:15













  • Just get rid of Edit: As "that other guy" write, this does not handle backslash. Not recommended. now - it handles backslash just fine by not interpreting it, and it is one of recommended approaches if/when you need that behavior.

    – Ed Morton
    Feb 16 at 14:48





















24














It seems that the good-old ENVIRON awk built-in hash is not mentioned at all. An example of its usage:



$ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
Solaris rxvt





share|improve this answer



















  • 3





    This is a good suggestion because it passes the data verbatim. -v doesn't work when the value contains backslashes.

    – that other guy
    Feb 23 '16 at 21:45






  • 1





    @thatotherguy I did not know that! I thought that if I use awk -v x='cd' ... then it will be used it properly. But when x is printed awk drops the famous: awk: warning: escape sequence 'c' treated as plain 'c' error message... Thanks!

    – TrueY
    Feb 24 '16 at 9:11





















8














Use either of these depending how you want backslashes in the shell variables handled (avar is an awk variable, svar is a shell variable):



awk -v avar="$svar" '... avar ...' file
awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file


See http://cfajohnson.com/shell/cus-faq-2.html#Q24 for details and other options. The first method above is almost always your best option and has the most obvious semantics.






share|improve this answer

































    5














    You could pass in the command-line option -v with a variable name (v) and a value (=) of the environment variable ("${v}"):



    % awk -vv="${v}" 'BEGIN { print v }'
    123test


    Or to make it clearer (with far fewer vs):



    % environment_variable=123test
    % awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
    123test





    share|improve this answer

































      3














      You can utilize ARGV:



      v=123test
      awk 'BEGIN {print ARGV[1]}' "$v"


      Note that if you are going to continue into the body, you will need to adjust
      ARGC:



      awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"





      share|improve this answer































        1














        I had to insert date at the beginning of the lines of a log file and it's done like below:



        DATE=$(date +"%Y-%m-%d")
        awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log


        It can be redirect to another file to save






        share|improve this answer
























        • The double quote - single quote - double quote was exactly what I needed to make mine work.

          – user53029
          Jul 21 '16 at 14:24











        • This was already mentioned in the accepted answer as a method you should not use due to code injection vulnerabilities. So the information here is redundant (already described in the accepted answer), and incomplete (does not mention the problems with this method).

          – Jason S
          Oct 12 '16 at 5:20



















        0














        I just changed @Jotne's answer for "for loop".



        for i in `seq 11 20`; do host myserver-$i | awk -v i="$i" '{print "myserver-"i" " $4}'; done





        share|improve this answer































          0














          for i in chr{1..22} chrX chrY
          do
          awk -v chr="$i" '$1==chr' ../snp150.hg19.txt >> $chr.vcf.bed
          echo $i
          done





          share|improve this answer






















            protected by Inian Apr 27 '18 at 19:37



            Thank you for your interest in this question.
            Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



            Would you like to answer one of these unanswered questions instead?














            8 Answers
            8






            active

            oldest

            votes








            8 Answers
            8






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            374














            Getting shell variables into awk



            may be done in several ways. Some are better than others. This should cover most of them. If you have a comment, please leave below.





            Using -v (The best way, most portable)



            Use the -v option: (P.S. use a space after -v or it will be less portable. E.g., awk -v var= not awk -vvar=)



            variable="line onenline two"
            awk -v var="$variable" 'BEGIN {print var}'
            line one
            line two


            This should be compatible with most awk, and the variable is available in the BEGIN block as well:



            If you have multiple variables:



            awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'


            Warning. As Ed Morton writes, escape sequences will be interpreted so t becomes a real tab and not t if that is what you search for. Can be solved by using ENVIRON or access it via ARGV





            Variable after code block



            Here we get the variable after the awk code. This will work fine as long as you do not need the variable in the BEGIN block:



            variable="line onenline two"
            echo "input data" | awk '{print var}' var="${variable}"
            or
            awk '{print var}' var="${variable}" file


            This also works with multiple variables
            awk '{print a,b,$0}' a="$var1" b="$var2" file



            Using variable this way does not work in BEGIN block:



            echo "input data" | awk 'BEGIN {print var}' var="${variable}"




            Here-string



            Variable can also be added to awk using a here-string from shells that support them (including Bash):



            awk '{print $0}' <<< "$variable"
            test


            This is the same as:



            printf '%s' "$variable" | awk '{print $0}'


            P.S. this treats the variable as a file input.






            ENVIRON input



            As TrueY writes, you can use the ENVIRON to print Environment Variables.
            Setting a variable before running AWK, you can print it out like this:



            X=MyVar awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
            MyVar /bin/bash





            ARGV input



            As Steven Penny writes, you can use ARGV to get the data into awk:



            v="my data"
            awk 'BEGIN {print ARGV[1]}' "$v"
            my data


            To get the data into the code itself, not just the BEGIN:



            v="my data"
            echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"
            my data test




            Variable within the code: USE WITH CAUTION



            You can use a variable within the awk code, but it's messy and hard to read, and as Charles Duffy points out, this version may also be a victim of code injection. If someone adds bad stuff to the variable, it will be executed as part of the awk code.



            This works by extracting the variable within the code, so it becomes a part of it.



            If you want to make an awk that changes dynamically with use of variables, you can do it this way, but DO NOT use it for normal variables.



            variable="line onenline two"
            awk 'BEGIN {print "'"$variable"'"}'
            line one
            line two


            Here is an example of code injection:



            variable='line onenline two" ; for (i=1;i<=1000;++i) print i"'
            awk 'BEGIN {print "'"$variable"'"}'
            line one
            line two
            1
            2
            3
            .
            .
            1000


            You can add lots of commands to awk this way. Even make it crash with non valid commands.





            Extra info:



            Use of double quote



            It's always good to double quote variable "$variable"

            If not, multiple lines will be added as a long single line.



            Example:



            var="Line one
            This is line two"

            echo $var
            Line one This is line two

            echo "$var"
            Line one
            This is line two


            Other errors you can get without double quote:



            variable="line onenline two"
            awk -v var=$variable 'BEGIN {print var}'
            awk: cmd. line:1: onenline
            awk: cmd. line:1: ^ backslash not last character on line
            awk: cmd. line:1: onenline
            awk: cmd. line:1: ^ syntax error


            And with single quote, it does not expand the value of the variable:



            awk -v var='$variable' 'BEGIN {print var}'
            $variable


            More info about AWK and variables



            Read this faq.






            share|improve this answer





















            • 1





              "messy and hard to read" ignores the more important security concern of code injection when directly substituting strings into awk code.

              – Charles Duffy
              Feb 18 '16 at 20:21






            • 1





              @CharlesDuffy. You are 100% correct. Cleaned up some more.

              – Jotne
              Feb 18 '16 at 21:07






            • 1





              @EdMorton. Thanks for the input. I am on different planet compare to you about this :) Most of this post are made and change due to comments by others. Updated post to reflect your comments.

              – Jotne
              Feb 16 at 7:15













            • Just get rid of Edit: As "that other guy" write, this does not handle backslash. Not recommended. now - it handles backslash just fine by not interpreting it, and it is one of recommended approaches if/when you need that behavior.

              – Ed Morton
              Feb 16 at 14:48


















            374














            Getting shell variables into awk



            may be done in several ways. Some are better than others. This should cover most of them. If you have a comment, please leave below.





            Using -v (The best way, most portable)



            Use the -v option: (P.S. use a space after -v or it will be less portable. E.g., awk -v var= not awk -vvar=)



            variable="line onenline two"
            awk -v var="$variable" 'BEGIN {print var}'
            line one
            line two


            This should be compatible with most awk, and the variable is available in the BEGIN block as well:



            If you have multiple variables:



            awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'


            Warning. As Ed Morton writes, escape sequences will be interpreted so t becomes a real tab and not t if that is what you search for. Can be solved by using ENVIRON or access it via ARGV





            Variable after code block



            Here we get the variable after the awk code. This will work fine as long as you do not need the variable in the BEGIN block:



            variable="line onenline two"
            echo "input data" | awk '{print var}' var="${variable}"
            or
            awk '{print var}' var="${variable}" file


            This also works with multiple variables
            awk '{print a,b,$0}' a="$var1" b="$var2" file



            Using variable this way does not work in BEGIN block:



            echo "input data" | awk 'BEGIN {print var}' var="${variable}"




            Here-string



            Variable can also be added to awk using a here-string from shells that support them (including Bash):



            awk '{print $0}' <<< "$variable"
            test


            This is the same as:



            printf '%s' "$variable" | awk '{print $0}'


            P.S. this treats the variable as a file input.






            ENVIRON input



            As TrueY writes, you can use the ENVIRON to print Environment Variables.
            Setting a variable before running AWK, you can print it out like this:



            X=MyVar awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
            MyVar /bin/bash





            ARGV input



            As Steven Penny writes, you can use ARGV to get the data into awk:



            v="my data"
            awk 'BEGIN {print ARGV[1]}' "$v"
            my data


            To get the data into the code itself, not just the BEGIN:



            v="my data"
            echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"
            my data test




            Variable within the code: USE WITH CAUTION



            You can use a variable within the awk code, but it's messy and hard to read, and as Charles Duffy points out, this version may also be a victim of code injection. If someone adds bad stuff to the variable, it will be executed as part of the awk code.



            This works by extracting the variable within the code, so it becomes a part of it.



            If you want to make an awk that changes dynamically with use of variables, you can do it this way, but DO NOT use it for normal variables.



            variable="line onenline two"
            awk 'BEGIN {print "'"$variable"'"}'
            line one
            line two


            Here is an example of code injection:



            variable='line onenline two" ; for (i=1;i<=1000;++i) print i"'
            awk 'BEGIN {print "'"$variable"'"}'
            line one
            line two
            1
            2
            3
            .
            .
            1000


            You can add lots of commands to awk this way. Even make it crash with non valid commands.





            Extra info:



            Use of double quote



            It's always good to double quote variable "$variable"

            If not, multiple lines will be added as a long single line.



            Example:



            var="Line one
            This is line two"

            echo $var
            Line one This is line two

            echo "$var"
            Line one
            This is line two


            Other errors you can get without double quote:



            variable="line onenline two"
            awk -v var=$variable 'BEGIN {print var}'
            awk: cmd. line:1: onenline
            awk: cmd. line:1: ^ backslash not last character on line
            awk: cmd. line:1: onenline
            awk: cmd. line:1: ^ syntax error


            And with single quote, it does not expand the value of the variable:



            awk -v var='$variable' 'BEGIN {print var}'
            $variable


            More info about AWK and variables



            Read this faq.






            share|improve this answer





















            • 1





              "messy and hard to read" ignores the more important security concern of code injection when directly substituting strings into awk code.

              – Charles Duffy
              Feb 18 '16 at 20:21






            • 1





              @CharlesDuffy. You are 100% correct. Cleaned up some more.

              – Jotne
              Feb 18 '16 at 21:07






            • 1





              @EdMorton. Thanks for the input. I am on different planet compare to you about this :) Most of this post are made and change due to comments by others. Updated post to reflect your comments.

              – Jotne
              Feb 16 at 7:15













            • Just get rid of Edit: As "that other guy" write, this does not handle backslash. Not recommended. now - it handles backslash just fine by not interpreting it, and it is one of recommended approaches if/when you need that behavior.

              – Ed Morton
              Feb 16 at 14:48
















            374












            374








            374







            Getting shell variables into awk



            may be done in several ways. Some are better than others. This should cover most of them. If you have a comment, please leave below.





            Using -v (The best way, most portable)



            Use the -v option: (P.S. use a space after -v or it will be less portable. E.g., awk -v var= not awk -vvar=)



            variable="line onenline two"
            awk -v var="$variable" 'BEGIN {print var}'
            line one
            line two


            This should be compatible with most awk, and the variable is available in the BEGIN block as well:



            If you have multiple variables:



            awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'


            Warning. As Ed Morton writes, escape sequences will be interpreted so t becomes a real tab and not t if that is what you search for. Can be solved by using ENVIRON or access it via ARGV





            Variable after code block



            Here we get the variable after the awk code. This will work fine as long as you do not need the variable in the BEGIN block:



            variable="line onenline two"
            echo "input data" | awk '{print var}' var="${variable}"
            or
            awk '{print var}' var="${variable}" file


            This also works with multiple variables
            awk '{print a,b,$0}' a="$var1" b="$var2" file



            Using variable this way does not work in BEGIN block:



            echo "input data" | awk 'BEGIN {print var}' var="${variable}"




            Here-string



            Variable can also be added to awk using a here-string from shells that support them (including Bash):



            awk '{print $0}' <<< "$variable"
            test


            This is the same as:



            printf '%s' "$variable" | awk '{print $0}'


            P.S. this treats the variable as a file input.






            ENVIRON input



            As TrueY writes, you can use the ENVIRON to print Environment Variables.
            Setting a variable before running AWK, you can print it out like this:



            X=MyVar awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
            MyVar /bin/bash





            ARGV input



            As Steven Penny writes, you can use ARGV to get the data into awk:



            v="my data"
            awk 'BEGIN {print ARGV[1]}' "$v"
            my data


            To get the data into the code itself, not just the BEGIN:



            v="my data"
            echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"
            my data test




            Variable within the code: USE WITH CAUTION



            You can use a variable within the awk code, but it's messy and hard to read, and as Charles Duffy points out, this version may also be a victim of code injection. If someone adds bad stuff to the variable, it will be executed as part of the awk code.



            This works by extracting the variable within the code, so it becomes a part of it.



            If you want to make an awk that changes dynamically with use of variables, you can do it this way, but DO NOT use it for normal variables.



            variable="line onenline two"
            awk 'BEGIN {print "'"$variable"'"}'
            line one
            line two


            Here is an example of code injection:



            variable='line onenline two" ; for (i=1;i<=1000;++i) print i"'
            awk 'BEGIN {print "'"$variable"'"}'
            line one
            line two
            1
            2
            3
            .
            .
            1000


            You can add lots of commands to awk this way. Even make it crash with non valid commands.





            Extra info:



            Use of double quote



            It's always good to double quote variable "$variable"

            If not, multiple lines will be added as a long single line.



            Example:



            var="Line one
            This is line two"

            echo $var
            Line one This is line two

            echo "$var"
            Line one
            This is line two


            Other errors you can get without double quote:



            variable="line onenline two"
            awk -v var=$variable 'BEGIN {print var}'
            awk: cmd. line:1: onenline
            awk: cmd. line:1: ^ backslash not last character on line
            awk: cmd. line:1: onenline
            awk: cmd. line:1: ^ syntax error


            And with single quote, it does not expand the value of the variable:



            awk -v var='$variable' 'BEGIN {print var}'
            $variable


            More info about AWK and variables



            Read this faq.






            share|improve this answer















            Getting shell variables into awk



            may be done in several ways. Some are better than others. This should cover most of them. If you have a comment, please leave below.





            Using -v (The best way, most portable)



            Use the -v option: (P.S. use a space after -v or it will be less portable. E.g., awk -v var= not awk -vvar=)



            variable="line onenline two"
            awk -v var="$variable" 'BEGIN {print var}'
            line one
            line two


            This should be compatible with most awk, and the variable is available in the BEGIN block as well:



            If you have multiple variables:



            awk -v a="$var1" -v b="$var2" 'BEGIN {print a,b}'


            Warning. As Ed Morton writes, escape sequences will be interpreted so t becomes a real tab and not t if that is what you search for. Can be solved by using ENVIRON or access it via ARGV





            Variable after code block



            Here we get the variable after the awk code. This will work fine as long as you do not need the variable in the BEGIN block:



            variable="line onenline two"
            echo "input data" | awk '{print var}' var="${variable}"
            or
            awk '{print var}' var="${variable}" file


            This also works with multiple variables
            awk '{print a,b,$0}' a="$var1" b="$var2" file



            Using variable this way does not work in BEGIN block:



            echo "input data" | awk 'BEGIN {print var}' var="${variable}"




            Here-string



            Variable can also be added to awk using a here-string from shells that support them (including Bash):



            awk '{print $0}' <<< "$variable"
            test


            This is the same as:



            printf '%s' "$variable" | awk '{print $0}'


            P.S. this treats the variable as a file input.






            ENVIRON input



            As TrueY writes, you can use the ENVIRON to print Environment Variables.
            Setting a variable before running AWK, you can print it out like this:



            X=MyVar awk 'BEGIN{print ENVIRON["X"],ENVIRON["SHELL"]}'
            MyVar /bin/bash





            ARGV input



            As Steven Penny writes, you can use ARGV to get the data into awk:



            v="my data"
            awk 'BEGIN {print ARGV[1]}' "$v"
            my data


            To get the data into the code itself, not just the BEGIN:



            v="my data"
            echo "test" | awk 'BEGIN{var=ARGV[1];ARGV[1]=""} {print var, $0}' "$v"
            my data test




            Variable within the code: USE WITH CAUTION



            You can use a variable within the awk code, but it's messy and hard to read, and as Charles Duffy points out, this version may also be a victim of code injection. If someone adds bad stuff to the variable, it will be executed as part of the awk code.



            This works by extracting the variable within the code, so it becomes a part of it.



            If you want to make an awk that changes dynamically with use of variables, you can do it this way, but DO NOT use it for normal variables.



            variable="line onenline two"
            awk 'BEGIN {print "'"$variable"'"}'
            line one
            line two


            Here is an example of code injection:



            variable='line onenline two" ; for (i=1;i<=1000;++i) print i"'
            awk 'BEGIN {print "'"$variable"'"}'
            line one
            line two
            1
            2
            3
            .
            .
            1000


            You can add lots of commands to awk this way. Even make it crash with non valid commands.





            Extra info:



            Use of double quote



            It's always good to double quote variable "$variable"

            If not, multiple lines will be added as a long single line.



            Example:



            var="Line one
            This is line two"

            echo $var
            Line one This is line two

            echo "$var"
            Line one
            This is line two


            Other errors you can get without double quote:



            variable="line onenline two"
            awk -v var=$variable 'BEGIN {print var}'
            awk: cmd. line:1: onenline
            awk: cmd. line:1: ^ backslash not last character on line
            awk: cmd. line:1: onenline
            awk: cmd. line:1: ^ syntax error


            And with single quote, it does not expand the value of the variable:



            awk -v var='$variable' 'BEGIN {print var}'
            $variable


            More info about AWK and variables



            Read this faq.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Mar 13 at 12:00









            Toby Speight

            17.4k134368




            17.4k134368










            answered Sep 29 '13 at 7:51









            JotneJotne

            29.9k83345




            29.9k83345








            • 1





              "messy and hard to read" ignores the more important security concern of code injection when directly substituting strings into awk code.

              – Charles Duffy
              Feb 18 '16 at 20:21






            • 1





              @CharlesDuffy. You are 100% correct. Cleaned up some more.

              – Jotne
              Feb 18 '16 at 21:07






            • 1





              @EdMorton. Thanks for the input. I am on different planet compare to you about this :) Most of this post are made and change due to comments by others. Updated post to reflect your comments.

              – Jotne
              Feb 16 at 7:15













            • Just get rid of Edit: As "that other guy" write, this does not handle backslash. Not recommended. now - it handles backslash just fine by not interpreting it, and it is one of recommended approaches if/when you need that behavior.

              – Ed Morton
              Feb 16 at 14:48
















            • 1





              "messy and hard to read" ignores the more important security concern of code injection when directly substituting strings into awk code.

              – Charles Duffy
              Feb 18 '16 at 20:21






            • 1





              @CharlesDuffy. You are 100% correct. Cleaned up some more.

              – Jotne
              Feb 18 '16 at 21:07






            • 1





              @EdMorton. Thanks for the input. I am on different planet compare to you about this :) Most of this post are made and change due to comments by others. Updated post to reflect your comments.

              – Jotne
              Feb 16 at 7:15













            • Just get rid of Edit: As "that other guy" write, this does not handle backslash. Not recommended. now - it handles backslash just fine by not interpreting it, and it is one of recommended approaches if/when you need that behavior.

              – Ed Morton
              Feb 16 at 14:48










            1




            1





            "messy and hard to read" ignores the more important security concern of code injection when directly substituting strings into awk code.

            – Charles Duffy
            Feb 18 '16 at 20:21





            "messy and hard to read" ignores the more important security concern of code injection when directly substituting strings into awk code.

            – Charles Duffy
            Feb 18 '16 at 20:21




            1




            1





            @CharlesDuffy. You are 100% correct. Cleaned up some more.

            – Jotne
            Feb 18 '16 at 21:07





            @CharlesDuffy. You are 100% correct. Cleaned up some more.

            – Jotne
            Feb 18 '16 at 21:07




            1




            1





            @EdMorton. Thanks for the input. I am on different planet compare to you about this :) Most of this post are made and change due to comments by others. Updated post to reflect your comments.

            – Jotne
            Feb 16 at 7:15







            @EdMorton. Thanks for the input. I am on different planet compare to you about this :) Most of this post are made and change due to comments by others. Updated post to reflect your comments.

            – Jotne
            Feb 16 at 7:15















            Just get rid of Edit: As "that other guy" write, this does not handle backslash. Not recommended. now - it handles backslash just fine by not interpreting it, and it is one of recommended approaches if/when you need that behavior.

            – Ed Morton
            Feb 16 at 14:48







            Just get rid of Edit: As "that other guy" write, this does not handle backslash. Not recommended. now - it handles backslash just fine by not interpreting it, and it is one of recommended approaches if/when you need that behavior.

            – Ed Morton
            Feb 16 at 14:48















            24














            It seems that the good-old ENVIRON awk built-in hash is not mentioned at all. An example of its usage:



            $ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
            Solaris rxvt





            share|improve this answer



















            • 3





              This is a good suggestion because it passes the data verbatim. -v doesn't work when the value contains backslashes.

              – that other guy
              Feb 23 '16 at 21:45






            • 1





              @thatotherguy I did not know that! I thought that if I use awk -v x='cd' ... then it will be used it properly. But when x is printed awk drops the famous: awk: warning: escape sequence 'c' treated as plain 'c' error message... Thanks!

              – TrueY
              Feb 24 '16 at 9:11


















            24














            It seems that the good-old ENVIRON awk built-in hash is not mentioned at all. An example of its usage:



            $ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
            Solaris rxvt





            share|improve this answer



















            • 3





              This is a good suggestion because it passes the data verbatim. -v doesn't work when the value contains backslashes.

              – that other guy
              Feb 23 '16 at 21:45






            • 1





              @thatotherguy I did not know that! I thought that if I use awk -v x='cd' ... then it will be used it properly. But when x is printed awk drops the famous: awk: warning: escape sequence 'c' treated as plain 'c' error message... Thanks!

              – TrueY
              Feb 24 '16 at 9:11
















            24












            24








            24







            It seems that the good-old ENVIRON awk built-in hash is not mentioned at all. An example of its usage:



            $ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
            Solaris rxvt





            share|improve this answer













            It seems that the good-old ENVIRON awk built-in hash is not mentioned at all. An example of its usage:



            $ X=Solaris awk 'BEGIN{print ENVIRON["X"], ENVIRON["TERM"]}'
            Solaris rxvt






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Nov 6 '14 at 12:46









            TrueYTrueY

            5,95912839




            5,95912839








            • 3





              This is a good suggestion because it passes the data verbatim. -v doesn't work when the value contains backslashes.

              – that other guy
              Feb 23 '16 at 21:45






            • 1





              @thatotherguy I did not know that! I thought that if I use awk -v x='cd' ... then it will be used it properly. But when x is printed awk drops the famous: awk: warning: escape sequence 'c' treated as plain 'c' error message... Thanks!

              – TrueY
              Feb 24 '16 at 9:11
















            • 3





              This is a good suggestion because it passes the data verbatim. -v doesn't work when the value contains backslashes.

              – that other guy
              Feb 23 '16 at 21:45






            • 1





              @thatotherguy I did not know that! I thought that if I use awk -v x='cd' ... then it will be used it properly. But when x is printed awk drops the famous: awk: warning: escape sequence 'c' treated as plain 'c' error message... Thanks!

              – TrueY
              Feb 24 '16 at 9:11










            3




            3





            This is a good suggestion because it passes the data verbatim. -v doesn't work when the value contains backslashes.

            – that other guy
            Feb 23 '16 at 21:45





            This is a good suggestion because it passes the data verbatim. -v doesn't work when the value contains backslashes.

            – that other guy
            Feb 23 '16 at 21:45




            1




            1





            @thatotherguy I did not know that! I thought that if I use awk -v x='cd' ... then it will be used it properly. But when x is printed awk drops the famous: awk: warning: escape sequence 'c' treated as plain 'c' error message... Thanks!

            – TrueY
            Feb 24 '16 at 9:11







            @thatotherguy I did not know that! I thought that if I use awk -v x='cd' ... then it will be used it properly. But when x is printed awk drops the famous: awk: warning: escape sequence 'c' treated as plain 'c' error message... Thanks!

            – TrueY
            Feb 24 '16 at 9:11













            8














            Use either of these depending how you want backslashes in the shell variables handled (avar is an awk variable, svar is a shell variable):



            awk -v avar="$svar" '... avar ...' file
            awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file


            See http://cfajohnson.com/shell/cus-faq-2.html#Q24 for details and other options. The first method above is almost always your best option and has the most obvious semantics.






            share|improve this answer






























              8














              Use either of these depending how you want backslashes in the shell variables handled (avar is an awk variable, svar is a shell variable):



              awk -v avar="$svar" '... avar ...' file
              awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file


              See http://cfajohnson.com/shell/cus-faq-2.html#Q24 for details and other options. The first method above is almost always your best option and has the most obvious semantics.






              share|improve this answer




























                8












                8








                8







                Use either of these depending how you want backslashes in the shell variables handled (avar is an awk variable, svar is a shell variable):



                awk -v avar="$svar" '... avar ...' file
                awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file


                See http://cfajohnson.com/shell/cus-faq-2.html#Q24 for details and other options. The first method above is almost always your best option and has the most obvious semantics.






                share|improve this answer















                Use either of these depending how you want backslashes in the shell variables handled (avar is an awk variable, svar is a shell variable):



                awk -v avar="$svar" '... avar ...' file
                awk 'BEGIN{avar=ARGV[1];ARGV[1]=""}... avar ...' "$svar" file


                See http://cfajohnson.com/shell/cus-faq-2.html#Q24 for details and other options. The first method above is almost always your best option and has the most obvious semantics.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Sep 29 '13 at 13:54

























                answered Sep 29 '13 at 13:22









                Ed MortonEd Morton

                113k1245103




                113k1245103























                    5














                    You could pass in the command-line option -v with a variable name (v) and a value (=) of the environment variable ("${v}"):



                    % awk -vv="${v}" 'BEGIN { print v }'
                    123test


                    Or to make it clearer (with far fewer vs):



                    % environment_variable=123test
                    % awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
                    123test





                    share|improve this answer






























                      5














                      You could pass in the command-line option -v with a variable name (v) and a value (=) of the environment variable ("${v}"):



                      % awk -vv="${v}" 'BEGIN { print v }'
                      123test


                      Or to make it clearer (with far fewer vs):



                      % environment_variable=123test
                      % awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
                      123test





                      share|improve this answer




























                        5












                        5








                        5







                        You could pass in the command-line option -v with a variable name (v) and a value (=) of the environment variable ("${v}"):



                        % awk -vv="${v}" 'BEGIN { print v }'
                        123test


                        Or to make it clearer (with far fewer vs):



                        % environment_variable=123test
                        % awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
                        123test





                        share|improve this answer















                        You could pass in the command-line option -v with a variable name (v) and a value (=) of the environment variable ("${v}"):



                        % awk -vv="${v}" 'BEGIN { print v }'
                        123test


                        Or to make it clearer (with far fewer vs):



                        % environment_variable=123test
                        % awk -vawk_variable="${environment_variable}" 'BEGIN { print awk_variable }'
                        123test






                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Sep 29 '13 at 7:57

























                        answered Sep 29 '13 at 7:49









                        JohnsywebJohnsyweb

                        99.8k18146212




                        99.8k18146212























                            3














                            You can utilize ARGV:



                            v=123test
                            awk 'BEGIN {print ARGV[1]}' "$v"


                            Note that if you are going to continue into the body, you will need to adjust
                            ARGC:



                            awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"





                            share|improve this answer




























                              3














                              You can utilize ARGV:



                              v=123test
                              awk 'BEGIN {print ARGV[1]}' "$v"


                              Note that if you are going to continue into the body, you will need to adjust
                              ARGC:



                              awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"





                              share|improve this answer


























                                3












                                3








                                3







                                You can utilize ARGV:



                                v=123test
                                awk 'BEGIN {print ARGV[1]}' "$v"


                                Note that if you are going to continue into the body, you will need to adjust
                                ARGC:



                                awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"





                                share|improve this answer













                                You can utilize ARGV:



                                v=123test
                                awk 'BEGIN {print ARGV[1]}' "$v"


                                Note that if you are going to continue into the body, you will need to adjust
                                ARGC:



                                awk 'BEGIN {ARGC--} {print ARGV[2], $0}' file "$v"






                                share|improve this answer












                                share|improve this answer



                                share|improve this answer










                                answered Jan 15 '17 at 7:05









                                Steven PennySteven Penny

                                1




                                1























                                    1














                                    I had to insert date at the beginning of the lines of a log file and it's done like below:



                                    DATE=$(date +"%Y-%m-%d")
                                    awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log


                                    It can be redirect to another file to save






                                    share|improve this answer
























                                    • The double quote - single quote - double quote was exactly what I needed to make mine work.

                                      – user53029
                                      Jul 21 '16 at 14:24











                                    • This was already mentioned in the accepted answer as a method you should not use due to code injection vulnerabilities. So the information here is redundant (already described in the accepted answer), and incomplete (does not mention the problems with this method).

                                      – Jason S
                                      Oct 12 '16 at 5:20
















                                    1














                                    I had to insert date at the beginning of the lines of a log file and it's done like below:



                                    DATE=$(date +"%Y-%m-%d")
                                    awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log


                                    It can be redirect to another file to save






                                    share|improve this answer
























                                    • The double quote - single quote - double quote was exactly what I needed to make mine work.

                                      – user53029
                                      Jul 21 '16 at 14:24











                                    • This was already mentioned in the accepted answer as a method you should not use due to code injection vulnerabilities. So the information here is redundant (already described in the accepted answer), and incomplete (does not mention the problems with this method).

                                      – Jason S
                                      Oct 12 '16 at 5:20














                                    1












                                    1








                                    1







                                    I had to insert date at the beginning of the lines of a log file and it's done like below:



                                    DATE=$(date +"%Y-%m-%d")
                                    awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log


                                    It can be redirect to another file to save






                                    share|improve this answer













                                    I had to insert date at the beginning of the lines of a log file and it's done like below:



                                    DATE=$(date +"%Y-%m-%d")
                                    awk '{ print "'"$DATE"'", $0; }' /path_to_log_file/log_file.log


                                    It can be redirect to another file to save







                                    share|improve this answer












                                    share|improve this answer



                                    share|improve this answer










                                    answered Mar 2 '16 at 8:07









                                    SinaSina

                                    32536




                                    32536













                                    • The double quote - single quote - double quote was exactly what I needed to make mine work.

                                      – user53029
                                      Jul 21 '16 at 14:24











                                    • This was already mentioned in the accepted answer as a method you should not use due to code injection vulnerabilities. So the information here is redundant (already described in the accepted answer), and incomplete (does not mention the problems with this method).

                                      – Jason S
                                      Oct 12 '16 at 5:20



















                                    • The double quote - single quote - double quote was exactly what I needed to make mine work.

                                      – user53029
                                      Jul 21 '16 at 14:24











                                    • This was already mentioned in the accepted answer as a method you should not use due to code injection vulnerabilities. So the information here is redundant (already described in the accepted answer), and incomplete (does not mention the problems with this method).

                                      – Jason S
                                      Oct 12 '16 at 5:20

















                                    The double quote - single quote - double quote was exactly what I needed to make mine work.

                                    – user53029
                                    Jul 21 '16 at 14:24





                                    The double quote - single quote - double quote was exactly what I needed to make mine work.

                                    – user53029
                                    Jul 21 '16 at 14:24













                                    This was already mentioned in the accepted answer as a method you should not use due to code injection vulnerabilities. So the information here is redundant (already described in the accepted answer), and incomplete (does not mention the problems with this method).

                                    – Jason S
                                    Oct 12 '16 at 5:20





                                    This was already mentioned in the accepted answer as a method you should not use due to code injection vulnerabilities. So the information here is redundant (already described in the accepted answer), and incomplete (does not mention the problems with this method).

                                    – Jason S
                                    Oct 12 '16 at 5:20











                                    0














                                    I just changed @Jotne's answer for "for loop".



                                    for i in `seq 11 20`; do host myserver-$i | awk -v i="$i" '{print "myserver-"i" " $4}'; done





                                    share|improve this answer




























                                      0














                                      I just changed @Jotne's answer for "for loop".



                                      for i in `seq 11 20`; do host myserver-$i | awk -v i="$i" '{print "myserver-"i" " $4}'; done





                                      share|improve this answer


























                                        0












                                        0








                                        0







                                        I just changed @Jotne's answer for "for loop".



                                        for i in `seq 11 20`; do host myserver-$i | awk -v i="$i" '{print "myserver-"i" " $4}'; done





                                        share|improve this answer













                                        I just changed @Jotne's answer for "for loop".



                                        for i in `seq 11 20`; do host myserver-$i | awk -v i="$i" '{print "myserver-"i" " $4}'; done






                                        share|improve this answer












                                        share|improve this answer



                                        share|improve this answer










                                        answered Apr 10 '18 at 7:34









                                        edibedib

                                        4031614




                                        4031614























                                            0














                                            for i in chr{1..22} chrX chrY
                                            do
                                            awk -v chr="$i" '$1==chr' ../snp150.hg19.txt >> $chr.vcf.bed
                                            echo $i
                                            done





                                            share|improve this answer




























                                              0














                                              for i in chr{1..22} chrX chrY
                                              do
                                              awk -v chr="$i" '$1==chr' ../snp150.hg19.txt >> $chr.vcf.bed
                                              echo $i
                                              done





                                              share|improve this answer


























                                                0












                                                0








                                                0







                                                for i in chr{1..22} chrX chrY
                                                do
                                                awk -v chr="$i" '$1==chr' ../snp150.hg19.txt >> $chr.vcf.bed
                                                echo $i
                                                done





                                                share|improve this answer













                                                for i in chr{1..22} chrX chrY
                                                do
                                                awk -v chr="$i" '$1==chr' ../snp150.hg19.txt >> $chr.vcf.bed
                                                echo $i
                                                done






                                                share|improve this answer












                                                share|improve this answer



                                                share|improve this answer










                                                answered Jul 20 '18 at 15:13









                                                Shicheng GuoShicheng Guo

                                                643715




                                                643715

















                                                    protected by Inian Apr 27 '18 at 19:37



                                                    Thank you for your interest in this question.
                                                    Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                                                    Would you like to answer one of these unanswered questions instead?



                                                    Popular posts from this blog

                                                    Bressuire

                                                    Vorschmack

                                                    Quarantine