Nap
Nap

Reputation: 8276

Setting multiple field to awk variables at once

I am trying to set an awk variable field to several field at once.

Right now I can only set the variables one by one.

for line in `cat file.txt`;do
    var1=`echo $line | awk -F, '{print $1}'`
    var2=`echo $line | awk -F, '{print $2}'`
    var3=`echo $line | awk -F, '{print $3}'`

    #Some complex code....
done

I think this is costly cause it parses the linux variable several times. Is there a special syntax to set the variable at once? I know that awk has a BEGIN and END block but the reason I am trying to avoid the BEGIN and END block is to avoid nested awk.

I plan to place another loop and awk code in the #Some complex code.... part.

for line in `cat file.txt`;do
    var1=`echo $line | awk -F, '{print $1}'`
    var2=`echo $line | awk -F, '{print $2}'`
    var3=`echo $line | awk -F, '{print $3}'`

    for line2 in `cat file_old.txt`;do
        vara=`echo $line2 | awk -F, '{print $1}'`
        varb=`echo $line2 | awk -F, '{print $2}'`

        # Do comparison of $var1,var2 and $vara,$varb , then do something with either
    done
done

Upvotes: 1

Views: 9791

Answers (3)

V H
V H

Reputation: 8587

#!/bin/bash    
FILE="/tmp/values.txt"

    function parse_csv() { 
    local lines=$lines;
    > $FILE
    OLDIFS=$IFS;
    IFS=","
    i=0
    for val in ${lines}
    do
      i=$((++i))
      eval var${i}="${val}"
    done
    IFS=$OLDIFS;
    for ((j=1;j<=i;++j))
    do
      name="var${j}"
      echo ${!name} >> $FILE
    done

    }

    for lines in `cat file_old.txt`;do
     parse_csv;
    done

The problem you have described has only got 3 values, would there be a chance that 3 values may differ and be 4 or 5 or undefined ?

if so the above will parse through the csv line by line and output each value at a time on a new line in a file called /tmp/values.txt

feel free to modify to match your requirements its far more dynamic than defining 3 values

Upvotes: 0

William Pursell
William Pursell

Reputation: 212354

Why are you using awk at all?

while IFS=, read var1 var2 var3; do
  ...
done < file.txt

Upvotes: 4

newfurniturey
newfurniturey

Reputation: 38456

You can use the IFS internal field separator to use a comma (instead of whitespace) and do the assignments in a while loop:

SAVEIFS=$IFS;
IFS=',';
while read line; do
    set -- $line;
    var1=$1;
    var2=$2;
    var3=$3;
    ...
done < file.txt

IFS=$SAVEIFS;

This will save a copy of your current IFS, change it to a , character, and then iterate over each line in your file. The line set -- $line; will convert each word (separated by a comma) into a numeric-variable ($1, $2, etc.). You can either use these variables directly, or assign them to other (more meaningful) variable names.

Alternatively, you could use IFS with the answer provided by William:

IFS=',';
while read var1 var2 var3; do
    ...
done < file.txt

They are functionally identical and it just comes down to whether or not you want to explicitly set var1=$1 or have it defined in the while-loop's head.

Upvotes: 4

Related Questions