hamad khan
hamad khan

Reputation: 369

finding min and maximum between two strings in a data file using linux

*KEYWORD
$TIME_VALUE = 1.4000002e+001
$STATE_NO = 15
$Output for State 15 at time = 14
*ELEMENT_SHELL_THICKNESS
1346995      25 1457683 1471891 1457727 1471929
9.953265e-001   9.953265e-001   9.953265e-001   9.953265e-001
1346996      25 1471891 1457685 1471930 1457727  
9.953963e-001   9.953963e-001   9.953963e-001   9.953963e-001
1346997      25 1457685 1471892 1471931 1471930
9.953437e-001   9.953437e-001   9.953437e-001   9.953437e-001
*End

So the desired output could be

min=9.953265e-001  on line  07   at  1346995
max=9.953963e-001  on line  09   at  1346996

A probable solution, if we know the line numbers, is

cat your_file | awk '
NR >= 6 && NR <= 11{at=$1;getline
if (max < $1){max=$1;max_line=NR;max_at=at}
if (min > $1){min=$1;min_line=NR;min_at=at}}
NR == 7{min=$1;min_line=NR;min_at=at}
END{
printf "min=%-13e on line  %02d at %8d\n", min, min_line, min_at
printf "max=%-13e on line  %02d at %8d\n", max, max_line, max_at}'

but what if I want to search between *Keyword and *End, because due to a small change in the file the string comes to the defined lines and its value is 0 so the minimum is set to zero.

I must mention that this good solution was provided by jfgagne in my previous question: min and max in certain lines of input file with the tag of line number.

Upvotes: 1

Views: 444

Answers (1)

tripleee
tripleee

Reputation: 189850

Add a state to your script. If your state variable is false, set it to true if you are looking at the start marker; in any event, skip to next line. If your state variable is true; if looking at end marker, set the state variable to false, and skip to the next line; otherwise, you are in the region; process the line as before.

awk '!there{if($1 == "*ELEMENT_SHELL_THICKNESS") there=1; next}
there&&/^\*End$/{there=0;next}
{at=$1;getline
  if (!max || max < $1){max=$1;max_line=NR;max_at=at}
  if (!min || min > $1){min=$1;min_line=NR;min_at=at}}
END{
  printf "min=%-13e on line  %02d at %8d\n", min, min_line, min_at
  printf "max=%-13e on line  %02d at %8d\n", max, max_line, max_at}' your_file

I assume the start marker is *ELEMENT_SHELL_THICKNESS as suggested by the code, rather than *KEYWORD as you say in the question. I removed the min and max initialization code, mostly out of laziness; if either can be zero, perhaps you should put it back in.

This also does away with the Useless Use of cat.

Upvotes: 2

Related Questions