Thanos
Thanos

Reputation: 586

Read the number of columns using awk/sed

I have the following test file

Kmax Event File - Text Format
1 4 1000 
65 4121 9426 12312 
56 4118 8882 12307 
1273 4188 8217 12309 
1291 4204 8233 12308 
1329 4170 8225 12303 
1341 4135 8207 12306 
63 4108 8904 12300 
60 4106 8897 12307 
731 4108 8192 12306 
...
ÿÿÿÿÿÿÿÿ

In this file I want to delete the first two lines and apply some mathematical calculations. For instance each column i will be $i-(i-1)*number. A script that does this is the following

#!/bin/bash

if test $1 ; then
   if [ -f $1.evnt ] ; then
      rm -f $1.dat
      sed -n '2p' $1.evnt | (read v1 v2 v3
      for filename in $1*.evnt ; do
         echo -e "Processing file $filename"
         sed '$d' < $filename > $1_tmp
         sed -i '/Kmax/d' $1_tmp
         sed -i '/^'"$v1"' '"$v2"' /d' $1_tmp
         cat $1_tmp >> $1.dat
      done
      v3=`wc -l $1.dat | awk '{print $1}' `
      echo -e "$v1 $v2 $v3" > .$1.dat
      rm -f $1_tmp)
   else
      echo -e "\a!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
      echo -e "  Event file $1.evnt doesn't exist  !!!!!!"
      echo -e "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
   fi   
else
   echo -e "\a!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
   echo -e "!!!!!  Give name for event files  !!!!!"
   echo -e "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
fi
awk '{print $1, $2-4096, $3-(2*4096), $4-(3*4096)}' $1.dat >$1_Processed.dat
rm -f $1.dat
exit 0

The file won't always have 4 columns. Is there a way to read the number of columns, print this number and apply those calculations?

EDIT The idea is to have an input file (*.evnt), convert it to *.dat or any other ascii file(it doesn't matter really) which will only include the number in columns and then apply the calculation $i=$i-(i-1)*number. In addition it will keep the number of columns in a variable, that will be called in another program. For instance in the above file, number=4096 and a sample output file is the following

65 25 1234 24
56 22 690 19
1273 92 25 21
1291 108 41 20
1329 74 33 15
1341 39 15 18
63 12 712 12
60 10 705 19
731 12 0 18

while in the console I will get the message There are 4 detectors.

Finally a new file_processed.dat will be produced, where file is the initial name of awk's input file.

The way it should be executed is the following

./myscript <filename>

where <filename> is the name without the format. For instance, the files will have the format filename.evnt so it should be executed using

./myscript filename

Upvotes: 0

Views: 179

Answers (2)

Ed Morton
Ed Morton

Reputation: 203358

Let's start with this to see if it's close to what you're trying to do:

$ numdet=$( awk -v num=4096 '
    NR>2 && NF>1 {
        out = FILENAME "_processed.dat"
        for (i=1;i<=NF;i++) {
            $i = $i-(i-1)*num
        }
        nf = NF
        print > out
    }
    END {
        printf "There are %d detectors\n", nf | "cat>&2"
        print nf
    }
    ' file )

There are 4 detectors

$ cat file_processed.dat
65 25 1234 24
56 22 690 19
1273 92 25 21
1291 108 41 20
1329 74 33 15
1341 39 15 18
63 12 712 12
60 10 705 19
731 12 0 18

$ echo "$numdet"
4

Is that it?

Upvotes: 3

BMW
BMW

Reputation: 45243

Using awk

awk 'NR<=2{next}{for (i=1;i<=NF;i++) $i=$i-(i-1)*4096}1' file

Upvotes: 1

Related Questions