Reputation: 925
I have the following output.txt
it consists only 2 columns to demonstrate:
Test1 Test1-IS-OK
Test2 Test2-IS-NOT
Test3 Test3-IS-OK
Test4 Test4-IS-OK
Test5 Test5-IS-NOT
Then my bash script has the following code:
#!/bin/bash
output="output.txt"
a=$(awk '{ print $1 }' $output)
b=$(awk '{ print $2 }' $output)
while IFS=" " read -r $a $b
do
echo "LOG: $a and $b"
done < "$output"
I got the following error:
./test.sh: line 13: read: `Test1-IS-OK': not a valid identifier
I need to have output like this
LOG: Test1 and Test1-IS-OK
LOG: Test2 and Test2-IS-NOT
LOG: Test3 and Test3-IS-OK
LOG: Test4 and Test4-IS-OK
LOG: Test5 and Test5-IS-NOT
But the code is not working. What is the best method to loop this 2 columns from a file? Is there a simpler method?
Upvotes: 4
Views: 3149
Reputation: 660
Please consider transferring the awk
parsing to the loop, where it belongs:
#!/bin/bash
output="output.txt"
while read -r line
do
a=$(echo "${line}" | awk '{print $1}')
b=$(echo "${line}" | awk '{print $2}')
echo "LOG: $a and $b"
done < "$output"
Edited according to a good suggestion by @EdMorton
Upvotes: 3
Reputation: 12465
Use this Perl one-liner:
perl -lane 'print "LOG: $F[0] and $F[1]";' output.txt > new.txt
The Perl one-liner uses these command line flags:
-e
: Tells Perl to look for code in-line, instead of in a file.
-n
: Loop over the input one line at a time, assigning it to $_
by default.
-l
: Strip the input line separator ("\n"
on *NIX by default) before executing the code in-line, and append it when printing.
-a
: Split $_
into array @F
on whitespace or on the regex specified in -F
option.
SEE ALSO:
perldoc perlrun
: how to execute the Perl interpreter: command line switches
Upvotes: 1
Reputation: 20032
What are the problems with your code?
a=$(awk '{ print $1 }' $output)
With echo "a=${a}"
you will see, that a is filled with the output for all lines. You were trying to make some find of function, to be called after $a
.
while IFS=" " read -r $a $b
Now you are trying to call the "functions" a and b. The code will substitue the value of the variables before reading the inputfile. when a is filled with "Test1 Test2" the code will try to fill the fields $Test1
and $Test2
.
When you only want to change the output, without passing the variables to another statement, you can use awk
, or
sed -E 's/([^ ]*) ([^ ]*).*/LOG: \1 and \2/' $output
# or
printf 'LOG: %s and %s\n' $(<$output)
In your case, you can make read
reading two parameters:
while read -r a b
do
echo "LOG: $a and $b"
done < "$output"
Upvotes: 2
Reputation: 786289
Best is to avoid bash and do this completely in awk. Within awk it is as simple as:
awk '{print "LOG:", $1, "and", $2}' file
LOG: Test1 and Test1-IS-OK
LOG: Test2 and Test2-IS-NOT
LOG: Test3 and Test3-IS-OK
LOG: Test4 and Test4-IS-OK
LOG: Test5 and Test5-IS-NOT
Upvotes: 7