1

I would like to run a script within an awk command. I have a code ./myscript that calculates the likelihood between two entities; the results are listed in listfile.txt.

The input for ./myscript is a file with two columns generated randomly.

The purpose here is to know what input file (values) is the best for the calculation. If the condition (0.01<$8<0.5) is not verified, the code keep running until it gives the best (random input)

I did try this, but it doesn't keep executing the code

./rand_input_generator
./myscript

rms=` awk ' NR==1 {print $8}' listfile.txt`
echo $rms

awk 'BEGIN {
rrr=$rms;
min=0.01;
max=0.5;
    while(rrr > max) {
    while(rrr < min) {
    system("./rand_input_generator");
    system("./myscript.cmd");
}
}
} ' 

I seems like it doesn't go into a loop at all. any suggestions please?

  • 2
    Your requirements are very vague, it sounds like you want to run `myscript` (is that a shell script or an awk script or something else?) if $8 is between 0 and 0.05 and also run it if it's between 0 and 0.5 but that doesn't make sense. In any case, there's probably a better way to do whatever it is you're trying to do. If you [edit] your question to show a [mcve] including your attempt to do whatever it is you're trying to do plus concise, testable sample input and expected output then we can help you. – Ed Morton Dec 09 '20 at 18:15
  • It looks like myscript manipulates the listfile.txt file that awk is processing at the same time as well. This will cause issues. – Raman Sailopal Dec 09 '20 at 20:13
  • Thank you Ed Morton, I edited the question, added the code I'm using. – Redouane Nouh Dec 10 '20 at 12:02
  • You realize that `rrr` is never going to change values in the loop, because it never gets reassigned after `myscript` gets called a second time? If it did enter the loop, it would never exit. Also you're doing all of this in a `BEGIN` block which makes me think you may be confused. – Vercingatorix Dec 10 '20 at 12:59
  • Any Idea how to work around that? I thought that since there's ./myscript outside awk aswell, it will get reassigned each time – Redouane Nouh Dec 10 '20 at 13:11
  • You've added awk code but still no sample input, expected output, nor the shell (?) scripts it calls so there's not much we can do to help you yet. Make sure that what you end up posting is a [mcve] that demonstrates the problem you're having using a minimal, complete example, not just whatever code and text files you happen to have lying around. – Ed Morton Dec 10 '20 at 14:41
  • wrt `rrr=$rms;` - awk is not shell. awk is a completely separate tool with it's own language, syntax, semantics, scope, etc. Do not expect to be able to use shell syntax within an awk script or to directly access shell variables within an awk script any more than you could within a C program. See [how-do-i-use-shell-variables-in-an-awk-script](https://stackoverflow.com/questions/19075671/how-do-i-use-shell-variables-in-an-awk-script) – Ed Morton Dec 10 '20 at 14:43

3 Answers3

1

Use awk's system() function:

Here an example

awk '{printf("%s ",$1); system("myscript " $2)}' file

the example is from this site https://unix.stackexchange.com/questions/72935/using-bash-shell-function-inside-awk

Aalexander
  • 4,987
  • 3
  • 11
  • 34
1

Use awk's system function. The return value is the exit code.

!($8 >= 0 && $8 <= 0.05) { system("./myscript") }
shilch
  • 1,435
  • 10
  • 17
  • Thank you Shilch, this helps. I'm actually using "system" There's no errors when I use your code, it just seems that it doesn't do any thing. – Redouane Nouh Dec 10 '20 at 12:04
0

I think I see your dilemma. Try this:

function getvalue()
{
    local -a rms
    ./rand_input_generator
    ./myscript

    # No need for invoking gawk -- use bash array
    read -a rms < listfile.txt
    # Output eighth column/word
    echo ${rms[7]}
    # Echo to stderr/terminal
    echo ${rms[7]} 1>&2
}

rrr=$(getvalue)
min=0.01;
max=0.5;

# Let awk do the comparison, and print out "true" command or "false" command,
# evaluate the command, and loop based on return code
while $(awk -v rms="${rrr}" -v min="${min}" -v max="${max}" 'BEGIN {if (rms < min || rms > max) print "true"; else print "false"}'); do
    # Refresh the value
    rrr=$(getvalue)
done

In reality awk is really a string-processing language, not a math language, so I'd recommend this change to the last three lines if you have bc:

# Call bc to evaluate expression, returning 1 or 0 based on result, and check
while [[ $(echo "(${rrr} < ${min}) || (${rrr} > ${max})" | bc) -eq 1 ]]; do
    rrr=$(getvalue)
done
Vercingatorix
  • 1,838
  • 1
  • 13
  • 22
  • Thank you very much, that seems to run faster,, but. only for the first part. The While part still doesn't do any thing. I only get to see the value of rms, no loop seems to be running. – Redouane Nouh Dec 10 '20 at 15:09
  • @RedouaneNouh see the comments under your question for how you can help us to help you. – Ed Morton Dec 10 '20 at 15:15
  • @RedouaneNouh I managed to foul it up; try it again. – Vercingatorix Dec 10 '20 at 15:51
  • Thank your @eewanco this works with || (or) whene I try with && it doesn't work. Thank you anyway – Redouane Nouh Dec 14 '20 at 09:12
  • @RedouaneNouh Why are you trying it with &&? A value cannot be both less than a minimum AND greater than a maximum -- that makes no sense!! Unless the minimum is greater than the maximum. – Vercingatorix Dec 14 '20 at 12:20