3

I have this variable:

collumn=2

I want to make it change with the 2rd column of the line that starts with john from a file, with awk.

For example, in this file sample.txt:

bill|copper|real|bruce
john|gold|fake|jhin
johny|silver|geniue|madrit

This doesn't work:

collumn=2
awk -F '|' /^jonh/ -v collumn="$2" sample.txt
echo "$collumn"

I want it to print gold.

Basically I want to change the value of a variable with awk.

5
  • i think its better.. i wasnt enough focused. i want to change the value of a variable with awk Oct 14, 2017 at 1:54
  • damn i didnt see that too Oct 14, 2017 at 2:40
  • well collumn=2 doesnt mean anything really im just making a program and the user will give how the line starts and the column, so the program will put the string in that location to the variable.. i want collumn to change value and take the value of the string in the 2nd collumn (2nd as an example) and starts only with john (john as an example) im not that good with my english :P in your file the command yould be like awk -F '|' /^ij/ -v collumn="$2" sample.txt if i echo collumn it wil print me kl in my file i think it will do the awk for johny too and i ll lose the value that i want Oct 14, 2017 at 3:32
  • i made it 2 so it would be simpler Oct 14, 2017 at 3:33
  • thanks :D sorry for the trouble im still new and its a bit hard for me Oct 14, 2017 at 4:05

1 Answer 1

3

You are using two languages: Bash and AWK.

Bash (which is your shell) and AWK are both programming languages, and they both allow you to store data in variables. But variables in your shell and variables in AWK are completely separate. Furthermore, variables in AWK no longer exist after your AWK script finishes. That is, once your awk command is done running, your AWK variables are gone.

You can pass text of the form var=val as a command-line argument to the awk command. This assigns a variable in AWK. It does not affect shell variables in any way. When you use the -v option (e.g., -v var=val), that tells the awk command to assign the variable before it runs your AWK script, but it is still an AWK variable, not a shell variable.

Your goal is to assign text from a specific column of a matched line to a shell variable. You can do that. But first, let's solve a simpler problem. This command finds rows that start with john and displays the contents of the second column of each such row. If you have just one row that starts that way, it displays one item. If you have no such rows, it displays nothing, and if you have multiple rows that start with john, then it will display multiple items on separate lines:

awk -F '|' '/^john/ { print $2 }' sample.txt

The AWK script in that command is /^john/ {print $2}. I have enclosed it in single quotes (' ') so that it is treated as a single string, and not modified by the shell, before being passed to the awk command. Otherwise the shell would interpret the AWK script as five separate words and operators for the shell itself (not AWK), which would lead to it taking just /^john/ as the AWK script. Everything after it would be treated as filenames to pass to awk, which would not work. The shell would also expand $2, and would perform word splitting and filename expansion (globbing) on the result (though enclosing $2 in double quotes as in your question would prevent splitting and globbing). You don't want any of those things to happen. In general, it is a good idea to enclose your AWK scripts in single quotes so they are passed faithfully to the awk command.

With the sample.txt file shown in your question, that command produces this output:

gold
silver

It prints text from two matching lines, rather than just one. Since you want just gold, you probably don't really want to match all lines that start with john. Instead, you probably want to match only lines where the entry in the first column is john exactly. (One of the benefits of solving a simpler version of a problem first is that it can help you to refine your knowledge of precisely what problem you want to solve.) You can select only lines whose first column entry is exactly john like this:

awk -F '|' '$1 == "john" { print $2 }' sample.txt

That displays:

gold

Now let's solve the full problem. Assigning to shell variables is not something that you can do in an AWK script. Not only is this not part of the AWK language, but the awk command would have to be implemented as a part of your shell in order for it to be possible. This doesn't mean you can't do what you want to do--you absolutely can. It just means that, instead of attempting to write AWK code to assign to a shell variable, you must use the shell itself to do it.

You have an awk command that displays the value you want assigned to a variable. So you can use command substitution in the shell to help you perform the assignment. This command assigns it to a shell variable called entry (but you can use whatever name you like instead of entry, such as column):

entry="$(awk -F '|' '$1 == "john" { print $2 }' sample.txt)"

That works because the shell replaces $( ) and everything inside it with the output produced by running the command inside it. That's command substitution. Note that, when you assign a shell variable like this, you must not have any spaces around the = sign.

(By the way, you may notice that the text john is colorized above as though it were not effectively quoted. That is actually a bug in the software that provides syntax highlighting on this website, which happens because it does not fully parse the contents of the outer " ", so it does not know that the inner " " is inside $( ). This is not a problem when you actually run the command, however.)

You can verify that gold was assigned to the entry shell variable by running:

echo "$entry"

That will display:

gold

For more information on variables in the AWK language, see this section 6.1.3 Variables in Gawk: Effective AWK Programming, which is the official documentation for GNU awk (gawk). Although it documents GNU awk, it explains what is specific to GNU awk and what can also be used in other implementations of the AWK language. The awk command in your Ubuntu system be either mawk or gawk, depending on what software you have installed and how you have configured it. One way to see which is to run awk -W version.

You must log in to answer this question.

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