sangi
sangi

Reputation: 531

Unix shell scripting: assign value from file to variable into while loop, and use this value outside the loop

I'm writing a shell script, where I have to extract the contents of a file which is of type:

type1|valueA
type2|valueB
type1|valueC
type2|valueD
type3|valueE
....
typen|valueZ.

For each type in column_1, I have a target variable, which concatenates the values of the same type, to get a result like this:

var1=valueA,valueC
var2=valueB,valueD
var3=valueE
.....

Script implements something like this:

var1="HELLO"  
var2="WORLD"  
...  
cat $file | while read record; do  
   #estract column_1 and column_2 from $record    
if [ $column_1 = "tipo1" ]; then  
   var1="$var1, column_2"  ## column_2 = valueB
elif ....  
....  
fi  
done

But when I try to use the value of any of the variables where I chained column_2:

    echo "$var1 - $var2"   

I get the original values:

    HELLO - WORLD.    

Searching the internet, I read that the problem is related to the fact that the pipeline creates a subshell where the actual values are copied.

Is there a way to solve this problem!?

Above all, there is a way that would fit for all types of shells, in fact, this script must run potentially on different shells!? I do not want to use file support on which to write the partial results.

Upvotes: 1

Views: 24383

Answers (4)

BMW
BMW

Reputation: 45223

Using awk

awk '{a[$1]=a[$1]==""?$2:a[$1] OFS $2}
END{for (i in a) print i"="a[i]}' FS=\| OFS=, file  

type1=valueA,valueC
type2=valueB,valueD
type3=valueE

Upvotes: 0

Dennis Williamson
Dennis Williamson

Reputation: 359865

You don't need to use cat. Piping something into while creates a subshell. When the subshell exits, the values of variables set in the loop are lost (as would be directory changes using cd as another example. Instead, you should redirect your file into the done:

while condition
do
    # do some stuff
done < inputfile

By the way, instead of:

while read record

you can do:

while IFS='|' read -r column1 column2

Upvotes: 3

Didier Trosset
Didier Trosset

Reputation: 37427

Oneliner:

for a in `awk "-F|" '{print $1;}' test | sort -u` ; do echo -n "$a =" ; grep -e "^$a" test | awk "-F|" '{ printf(" %s,", $2);}' ; echo "" ; done

Upvotes: 0

Related Questions