LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Passing a list of variables to a for loop (https://www.linuxquestions.org/questions/linux-newbie-8/passing-a-list-of-variables-to-a-for-loop-869283/)

pdr_dan 03-17-2011 06:47 PM

Passing a list of variables to a for loop
 
Hi, I'm trying to do substitutions to a file based on passed variables. For example, I have a file called test.txt that has 5 lines:
cond0
cond1 or cond0
cond2
cond4
cond0

What I want to do is to go through that file, line by line and check for the presence of a passed variable in that line. If I have a match, then substitute and print, otherwise print line as is. My problem arises in that the number of variables is well, variable. The code I started with was the following:
passed variables were: earth wind fire


Code:

args=("$@")
for ((i=0 ; i < $# ; i++ ))     
do
  gawk -v cin="cond${i}" -v cout="${args[i]}" '{gsub(cin,cout);print $0}" >> test.out
done

What I was hoping for was test.out to look like this:
earth
wind or earth
fire
cond4
earth

What I get is a much longer file like this:
earth
cond1 or earth
cond2
...

This makes sense after thinking about it but is there anyway to get an output like the first case? Any help would be appreciated!

Dan

jlinkels 03-17-2011 08:33 PM

Quote:

Originally Posted by pdr_dan (Post 4294435)
Code:

args=("$@")
for ((i=0 ; i < $# ; i++ ))     
do
  gawk -v cin="cond${i}" -v cout="${args[i]}" '{gsub(cin,cout);print $0}" >> test.out
done


Are you sure $args[i] should not read $args[$i]?

Furthermore, run your script using sh -x yourscript, you'll see all values of your variables, and see if $i is being substituted correctly.

jlinkels

pdr_dan 03-18-2011 01:38 PM

Thanks for your reply jlinkels, and the info about "sh" that will make my life easier. The actual substitution works fine, the problem is more of a logical one. Given that I don't know the number of variables to be passed, is there anyway to do the substitution in a loop (or whatever) that doesn't generate repeats. For instance, the way I have it set up now (and btw, there was an error in the original code, the gawk line should have had the test.txt input file before the test.out output file), it goes through the file once for each variable and substitutes for that variable. This ends up generating an output file 3X longer than the input file, eg
earth
cond1 or earth
cond2
cond4
earth *then the next variable is checked
cond0
wind or cond0
cond2
cond4
cond0 *then the third would be checked
cond0
cond1 or cond0
fire
cond4
cond0

I can't think of a way to do a single pass with all the variables IF you don't know how many variables there are beforehand. There probably won't be more than 5 variables so I guess I could do something clunky like using a case statement to check the number of variables and execute a specific substitution statement depending on the number. Seems like there should be a better way but I can't think of one.

ButterflyMelissa 03-18-2011 02:49 PM

Yo,

Okay, fist off, I HOPE to add something sensible to this, if not do tell me...I want to learn, this is one of my ways to do just that :D

Is that PERL? If so, add the "satisfying" result to a string after checking if it's not already in there...
My PERL stinks (sorry) but my logical lego blocks are still there

Quote:

if (rindex($results,$incomming)!=-1)
{
print 'match';
} else
{
print 'no match';
$results = $results . $incomming;
}
And hey, if I'm off-topic here, just say so...it's okay :)

Thor

Sources:
http://www.devdaily.com/perl/edu/art...pl010003.shtml
and
http://www.tutorialspoint.com/perl/perl_rindex.htm

grail 03-19-2011 02:02 AM

So I see a couple of problems, the biggest you have is that gawk does not make changes to a file and since you are appending all changes to the same test.out it will only ever get
longer with each growing change. Also, looking at your code I believe there are typos and missing pieces as what you have shown would never work (I refer here to the gawk line that
has no input file and the actions start with a single quote but end in a double??

That aside, I see at least 2 obvious solutions:

1. Do the whole thing in gawk and place your changes in their own file (ie the words to pass in earth and so on)
2. Use sed to make the changes to the original file on each iteration

My preference would be sed:
Code:

#!/bin/bash

cp test.txt test.out

for arg
do
    sed -i "s/cond$((i++))/$arg/g" test.out
done

Quote:

Are you sure $args[i] should not read $args[$i]?
@jinkels - Yes the 'i' does not require quoting when used as an index for an array (numeric only of course)

pdr_dan 03-21-2011 12:38 PM

that did it, thanks everyone for your input!


All times are GMT -5. The time now is 09:33 AM.