0

I have a number of variables in a .dat file that I automatically changed with a script. One of these files has a parameter, bar, that is arranged as such in a .dat file:

var1  var2   var3  foo  bar
T     T      T     100  100

I used to use the following lines of a bash script to change the value of bar from an arbitrary initial value to the desired value, in this case 2000. This script would change 'bar' to 2000.

LINE1=$(awk '/bar/ {++n;if (n==1) {print FNR}}' data.dat)
((LINE1=$LINE1 + 1))
OLD1=$(awk '{for(i=1;i<'$LINE1';i++) getline}{print $12}' data.dat)
sed -i '' "${LINE1}s/$OLD1/2000/" data.dat

However, I now must now change foo alongside bar. In this example, this is setting foo and bar both to 2000.

LINE1=$(awk '/foo/ {++n;if (n==1) {print FNR}}' data.dat)
((LINE1=$LINE1 + 1))
OLD1=$(awk '{for(i=1;i<'$LINE1';i++) getline}{print $12}' data.dat)
sed -i '' "${LINE1}s/$OLD1/2000/" data.dat

LINE1=$(awk '/bar/ {++n;if (n==1) {print FNR}}' data.dat)
((LINE1=$LINE1 + 1))
OLD1=$(awk '{for(i=1;i<'$LINE1';i++) getline}{print $12}' data.dat)
sed -i '' "${LINE1}s/$OLD1/2000/" data.dat

This instead only changed the foo to 2000 while leaving bar unchanged. I realize that this is an issue with the way I've described the regular expression, but I have been unable to change both variables with an awk/sed expression.

2
  • Pls post the file fort.4 so people can follow your logics. Do you want to change the bar text or the number 100?
    – RudiC
    Commented Sep 20, 2018 at 16:18
  • The fort.4 was an accidental insertion, the file to be edited is data.dat. The var 1/var 2/var 3/ lines are now representative of the data.dat file. I'm trying to change the arguments to foo and bar rather than the strings foo and bar
    – eoncarlyle
    Commented Sep 20, 2018 at 18:04

2 Answers 2

0

You can do

awk -v newvalue=2000 '
    NR == 1 {
        for (i=1; i<=NF; i++) {
            if ($i == "foo") i_foo=i
            if ($i == "bar") i_bar=i
        }
    }
    NR == 2 {$i_foo = $i_bar = newvalue}
    {print}
' file.dat | column -t
var1  var2  var3  foo   bar
T     T     T     2000  2000

Or, with less hard-coding in the awk

awk -v cols="var2=1234,bar=5678" '
    BEGIN {
        n = split(cols, a, /[=,]/)
        for (i=1; i<n; i+=2) newval[a[i]] = a[i+1]
    }
    NR == 1 { for (i=1; i<=NF; i++) if ($i in newval) idx[$i] = i }
    NR == 2 { for (col in idx) $(idx[col]) = newval[col] }
    {print}
' file.dat | column -t
var1  var2  var3  foo  bar
T     1234  T     100  5678
2
  • Is there a way to do this to in-place change file.dat?
    – eoncarlyle
    Commented Sep 22, 2018 at 16:08
  • With GNU awk gawk -i inplace '... Commented Sep 22, 2018 at 23:25
0

Just for fun:

awk -F'\t' -vOFS='\t' -vfoovalue=2101 -vbarvalue=2102 '
             /foo/&&/bar/{
                           row=NR
                           for(i=1;i<=NF;i++){
                                               if($i=="foo"){colfoo=i}
                                               if($i=="bar"){colbar=i}
                                              }
                           print
                          }
             NR==row+1{ $colfoo=foovalue; $colbar=barvalue; print }
            ' file

var1    var2    var3    foo         bar
T       T       T       2101        2102

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.