Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Appending columns to a file using awk

Tags:

awk

I have a somewhat long awk script and I want to append two columns at the "right hand side" of the file. I have the following file in progress:

Node    temporary_Temperature   steady_Temperature  temporary_Sight steady_Sight    
1                   x                   x                   -                   -                   
2                   x                   x                   -                   -                   
3                   -                   -                   -                   -                   
4                   -                   -                   -                   -                   
5                   x                   x                   x                   -                   
6                   -                   -                   -                   -                   
7                   -                   -                   -                   -                   
8                   -                   -                   -                   -                   
9                   -                   -                   -                   -                   
10                  -                   -                   -                   -                   
11                  -                   -                   -                   -                   
12                  -                   -                   -                   -                   
13                  x                   x                   -                   -                   
14                  x                   x                   -                   -                   
15                  x                   -                   -                   -                   
16                  -                   -                   -                   -                   

The data are already written to a file and I want to iterate the lines in this file using awk and, let's say, append two more columns. At the header row I want to append the columns foo and bar, and thereafter append x or - to each line depending on other stuff. How can I achieve this? Since I am in the middle of a longer script I do not want to use sed unless there is some way to invoke sed from within an awk script amd print to the same file?

like image 567
Krøllebølle Avatar asked Jul 05 '26 17:07

Krøllebølle


2 Answers

The problem you may face here is that whenever awk modifies fields, it re-writes your $0, replacing IFS with OFS. If your FS is "any amount of whitespace" (the default FS), and it gets replaced with "a space" (the default OFS), you lose formatting.

To demonstrate:

[ghoti@pc ~]$ printf 'one    two\tthree\n'
one    two      three
[ghoti@pc ~]$ printf 'one    two\tthree\n' | awk '{$4 = "four"} 1'
one two three four

If you don't really want to modify the fields of each line, and you just want to apend a string, you can do that without rewriting your field separators:

[ghoti@pc ~]$ printf 'one    two\tthree\n' | awk '{print $0 "\tfour"}'
one    two      three   four

Without seeing your script, or the kind of data you want to append, it's difficult for me to provide specific examples that I know will be applicable to your situation, but here's an example to get you started:

  NR == 1 {
    print $0 "\tfoo\tbar";
    next;
  }
  {
    print $0 "\t" (conditionone ? "x" : "-") "\t" (conditiontwo ? "x" : "-");
  }

If you need help crafting the conditions, please include them in your question. I've used short-forms in the code above; you could obviously space things out and make multiple-line prints using printf(), or set variables based on the two conditions to be included in your print.

As an alternative, you could just re-do your formatting as you go through the input data. For example (assuming the trailing spaces in your question are really what your input file looks like):

BEGIN {
  fmt="%-20s%-20s%-20s%-20s%-20s%-20s%s\n";
}

NR == 1 {
  printf("%s%12s%-20s%-20s\n", $0, " ", "foo", "bar");
  next;
}

{ foo="-"; bar="-"; }

conditionone { foo="x"; }
conditiontwo { bar="x"; }

{
  printf(fmt, $1, $2, $3, $4, $5, foo, bar);
}

You'd probably have to fiddle with your spacing on line 1.

like image 56
ghoti Avatar answered Jul 08 '26 22:07

ghoti


If it's the formatting that's a problem, pipe the output through column -t

Example:

awk '
    NR==1 {print $0, "foo", "bar"; next} 
    {print $0, ($2=="x"?"-":"x"), ($4=="x"?"-":"x")}
' file | column -t

outputs

Node  temporary_Temperature  steady_Temperature  temporary_Sight  steady_Sight  foo  bar
1     x                      x                   -                -             -    x
2     x                      x                   -                -             -    x
3     -                      -                   -                -             x    x
4     -                      -                   -                -             x    x
5     x                      x                   x                -             -    -
6     -                      -                   -                -             x    x
7     -                      -                   -                -             x    x
8     -                      -                   -                -             x    x
9     -                      -                   -                -             x    x
10    -                      -                   -                -             x    x
11    -                      -                   -                -             x    x
12    -                      -                   -                -             x    x
13    x                      x                   -                -             -    x
14    x                      x                   -                -             -    x
15    x                      -                   -                -             -    x
16    -                      -                   -                -             x    x
like image 40
glenn jackman Avatar answered Jul 08 '26 21:07

glenn jackman