0

I tried to use awk to select all rows with a value greater than 98 in the third column. In the output, only lines between 98 - 98.99... were selected and lines with a value more than 98.99 not.

I would like to extract all lines with a value greater than 98 including 99, 100 and so on.

Here my code and my input format:

for i in *input.file; do awk '$3>98' $i >{i/input./output.}; done

A   chr11   98.80   83  1   0   2   84

B   chr7    95.45   22  1   0   40  61

C   chr7    88.89   27  0   1   46  72

D   chr6    100.00  20  0   0   1   20

Expected Output

A   chr11   98.80   83  1   0   2   84

D   chr6    100.00  20  0   0   1   20
10
  • No, no... simply awk '$3 > 98' *input.file (which will use the default print to output) Commented Jun 23, 2020 at 7:12
  • 98.01, 98.23, 98.45, ... 98.99 Commented Jun 23, 2020 at 7:16
  • 1
    Yes, you do it all with awk. No shell loop. Just awk '$3 > 98' *input.file Is it redirecting to output.file where you are confused? Commented Jun 23, 2020 at 7:17
  • I think >{i/input./output.} is missing a $ Commented Jun 23, 2020 at 7:18
  • awk '$3 > 98' *input.file didnt work, i got the same output :/ Commented Jun 23, 2020 at 7:19

1 Answer 1

3

Okay, if you have a series of files, *input.file and you want to select those lines where $3 > 98 and then write the values to the same prefix, but with output.file as the rest of the filename, you can use:

awk '$3 > 98 {
    match (FILENAME,/input.file$/)
    print $0 > substr(FILENAME,1,RSTART-1) "output.file"
}' *input.file

Which uses match to find the index where input.file begins and then uses substr to get the part of the filename before that and appends "output.file" to the substring for the final output filename.

match() sets the RSTART value to the index where input.file begins in the current filename which is then used by substr truncate the current filename at that index. See GNU awk String Functions for complete details.

For exmaple, if you had input files:

$ ls -1 *input.file
v1input.file
v2input.file

Both with your example content:

$ cat v1input.file
A chr11 98.80 83 1 0 2 84

B chr7 95.45 22 1 0 40 61

C chr7 88.89 27 0 1 46 72

D chr6 100.00 20 0 0 1 20

Running the awk command above would results in two output files:

$ ls -1 *output.file
v1output.file
v2output.file

Containing the records where the third-field was greater than 98:

$ cat v1output.file
A chr11 98.80 83 1 0 2 84
D chr6 100.00 20 0 0 1 20
Sign up to request clarification or add additional context in comments.

2 Comments

match (FILENAME,/input.file$/) and substr(FILENAME,1,RSTART-1) "output.file" are being done once per output line for every file, they only need to be done once per output (or input would be OK) file total for efficiency. Not closing the output files as you go means your awk will fail with a "too many open files" error after creating a doczen or so output files unless you're using GNU awk. Input/output redirection to/from an unparenthesized expression is undefined behavior per POSIX so it'll only work in some awks.
So do this instead: awk 'FNR==1{ close(out); match(FILENAME,/input\.file$/); out=substr(FILENAME,1,RSTART-1) "output.file" } $3 > 98{ print > out }' *input.file for efficiency and portability to all awks.

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.