AWK - Transmission of a variable with getline to system ()?
Asked Answered
K

1

7

I have a theoretical question:

1) How pass a variable to the system of getline ()?

awk 'BEGIN{var="ls"; var | getline var; system("echo $var")}'

2) How to assign a variable the output system ("ls") and print the result in awk?

awk 'BEGIN{var="system("ls")"; print '$var'}'

3) Can you assign a variable in the system (var = "ls") and print the result in awk?

awk 'BEGIN{system(var="ls"); print "'"$var"'"}'

Thank you for the information.

EDIT:

torek: Thank you for your response.

I understand that in the first example, you can do this:

awk 'BEGIN { while ("ls -l" | getline var) system("echo " var  );}'

For this application, you can not assign a variable output from system ()? As in this example:

awk 'BEGIN {var="ls -l"; system(var); print var}'
Khajeh answered 4/4, 2012 at 9:27 Comment(0)
R
16

You're looking at this the wrong way, I think. Awk's system just takes any old string, so give it one, e.g.:

system("echo " var);  # see side note below

(remember that in awk, strings are concatenated by adjacency). Moreover, system just runs a command; to capture its output, you need to use getline, similar to your question #1.

If you want to read all the output of ls you need to loop over the result from getline:

awk 'BEGIN { while ("ls" | getline var) print "I got: " var; }'

Since this defines only a BEGIN action, awk will start up, run ls, collect each output line and print it, and then exit.


Side note: be very careful with variables passed to a shell (this includes both calls to system and items on the left hand side of | getline, plus some other cases in modern varieties of awk—anything that runs a command). Backquotes, $(command), and semicolons can all allow users to invoke arbitrary commands. For instance, in the system("echo " var) example above, if var contains ; rm -rf $HOME the command becomes echo ; rm -rf $HOME, which is almost certainly not something you want to have happen.

You can check for "bad" characters and either object, or quote them. Modern 8-bit-clean shells should only require quoting quotes themselves (for syntactic validity), $, <, >, |, and `. If you use single quotes to quote arguments (to make them appear as a single "word"), you need only escape the single quotes. See this unix.stackexchange.com answer for more details.


One other side note: I tend to add "unnecessary" semicolons to my awk scripts, making them look more like C syntactically. Old habit from decades ago.

Ramey answered 4/4, 2012 at 9:49 Comment(5)
torek: Thank you for your response. For this application, you can not assign a variable output from system ()? As in this example: awk 'BEGIN {var="ls -l"; system(var); print var}'Khajeh
The system function: (1) runs something to completion; then (2) returns its exit value. ls has an exit value of 0 on success. So, you can do x = system(foo); print "ran " foo " and got " x; for instance. If foo is the string "ls", this will run ls with output going to awk's stdout, and set x to 0 because ls will succeed.Ramey
Note that it is important to escape user-supplied parameters as shown in this Unix.SE answer. Consider this example: awk '{ system("echo " $0); }'. This command is supposed to show every line from a file, but a line such as bye; rm /etc/passwd` will cause bye to be printed before your /etc/passwd file gets removed.Inessa
@Lekensteyn: agreed. The examples above were using known fixed (hard-coded) inputs like "ls" and trying to capture the output. As always, if users are allowed to generate inputs, someone must verify and/or encode them before passing them on. Otherwise Little Bobby Tables wreaks havoc.Ramey
@Ramey Yesterday I was also thinking of mommy exploit :P But in this context, ; DROP TABLE students does not make sense unless you have a command DROP. Can you add something about escaping input to your answer? I see the OP doing system("echo " var) which is definitely a bad idea.Inessa

© 2022 - 2024 — McMap. All rights reserved.