1

I am struggling to use a variable I set in a while loop for awk.

For example, I have a file that contains this:

1-WW
(2, 17.0)       (3, 25.0)       (4, 32.0)       (5, 37.0)       (6, 42.0)       (7, 46.0)       (8, 50.0)       (9, 53.0)       (10, 56.0)      (11, 59.0)      (12, 62.0)      (13, 65.0)   (14, 67.0)    (15, 70.0)       (16, 72.0)      (17, 74.0)      (18, 77.0)      (19, 79.0)      (20, 81.0)      (21, 83.0)      (22, 84.0)      (23, 86.0)      (24, 88.0)      (25, 89.0)      (26, 90.0)   (27, 90.0)
5-Ferm
(2, 16.0)       (3, 24.0)       (4, 29.0)       (5, 34.0)       (6, 37.0)       (7, 41.0)       (8, 43.0)       (9, 46.0)       (10, 48.0)      (11, 50.0)      (12, 52.0)      (13, 54.0)      (14, 56.0)      (15, 58.0)      (16, 59.0)

The aim of the loop is to:

  1. Take the line that starts with "^(" and make it into a text file with two columns -DONE
  2. Sort file based on column two and assign the max value to variable called max -DONE
  3. Find rows where column 2 == $max and find the min values of column $1 and append to output -HELP!

The loop I have made is as below. It is quite clunky as I am rather new to bash and still very much learning! I am struggling with calling my variable $max into the final awk line. any advice would be welcome!

I am using a while loop as the actual file I will be using has mutliple lines like the example above and I want to do this process for each line that starts with "^(" I have tried many variations on assigning the variable into awk, following many of the answers to questions on here but I cant seem to get any to work!

#!/usr/bin/env bash

# read through all lines and if the start with "(" do ...
while IFS='\t' read -r LINE || [ -n "${LINE}" ]; do
        if [[ "${LINE}" == "("* ]]; then
                echo "line: ${LINE}"; # print out line to make sure correct
                echo "${LINE}" | xargs -n 2 | sed 's/(//g' | sed 's/)//g' | awk -F"," '$1=$1' OFS="\t" > loop_test; # make all (,) into two columns and read into loop_test
                cat loop_test;
                max= sort -nrk2,2 loop_test | awk '{print $2}' | head -n 1 # sort by columns 2 and find largest value - input to variable max
                echo $max # check variable max has been assinged
                awk -v var="$max" '{ if ($2 == var) { print } }' loop_test | sort -nrk1,1 | tail -n 1 | awk '{print $1}' >> out # now find all rows where column 2 = $max and find lowest value of column 1 - send value to ouptut
        fi
done < test

The expected output should be a file called out like so:

26
16

Thank you in advance for your help and suggestions :)

5
  • First of all special thanks for adding your efforts in form of code, keep it up. Only thing could you please do add samples of input and expected output too more clearly in your question and let us know then. Commented May 1, 2020 at 10:11
  • 1
    max= sort | .... -> max=$(sort | ... ) Commented May 1, 2020 at 10:42
  • I have editied my question as you suggest - thank you. Although @KamilCuk has solved my problem and it works! Thank you :D How do I accept this as the answer if it is a comment? Commented May 1, 2020 at 11:45
  • Please check your expected output for that 2nd sample input line you provided - I think it should be 16, not 30. See also why-is-using-a-shell-loop-to-process-text-considered-bad-practice Commented May 1, 2020 at 11:46
  • oh yes it is 16 sorry! Edited now Commented May 1, 2020 at 11:48

1 Answer 1

1

With any POSIX awk:

$ cat tst.awk
BEGIN { FS="[)(,[:space:]]+" }
/^\(/ {
    delete vals
    max = $3
    vals[$3] = $2
    for (i=5; i<=NF; i+=2) {
        if ( $i > max ) {
            max = $i
            vals[$i] = ($i in vals ? vals[$i] " " : "") $(i-1)
        }
    }
    split(vals[max],p)
    min = p[1]
    for (i in p) {
        min = (p[i] < min ? p[i] : min)
    }
    print min
}

$ awk -f tst.awk file
26
16
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.