LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 01-31-2008, 04:31 AM   #1
muazfarooqaslam
LQ Newbie
 
Registered: Dec 2007
Posts: 22

Rep: Reputation: 15
Using for loop on 2 variables


Hi,

I have 2 variables containing a list of entries and i want to loop over them at the same time and not nested for loops. For e.g.

The two varibales are MSISDN and FIRST_NAME

for i in $MSISDN, j in $FIRST_NAME
do
echo -n Si
echo $j
done

but this way it is not working. I am using bash shell

Please help me with this.

Thanks
 
Old 01-31-2008, 12:23 PM   #2
Tinkster
Moderator
 
Registered: Apr 2002
Location: in a fallen world
Distribution: slackware by choice, others too :} ... android.
Posts: 23,066
Blog Entries: 11

Rep: Reputation: 910Reputation: 910Reputation: 910Reputation: 910Reputation: 910Reputation: 910Reputation: 910Reputation: 910
I'm not sure I understand what you're after ... are those
variable in pairs? If so, why don't you use an array?


Cheers,
Tink

Last edited by Tinkster; 01-31-2008 at 04:27 PM. Reason: sleep deprivation induced spelling horrors
 
Old 01-31-2008, 02:25 PM   #3
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976
You can easily use arrays - as Tinkster suggested - or file descriptors and a slightly different approach:
Code:
#!/bin/bash
# -----------------------------------------------------
#  Test variables
# -----------------------------------------------------
MSISDN="field1 field2 field3"
FIRST_NAME="value1 value2 value3"

# -----------------------------------------------------
#  Link file descriptors 4 and 5 to the values of the
#  vars using process substitution. Be sure to put an
#  extra trailing space inside quotes
# -----------------------------------------------------
exec 4< <(echo "$MSISDN ")
exec 5< <(echo "$FIRST_NAME ")

# -----------------------------------------------------
#  Read from the two file descriptors simultaneously
#  using a single blank space as delimiter (instead
#  of newline)
# -----------------------------------------------------
while read -d ' ' i <&4 && read -d ' ' j <&5
do
  echo $i
  echo $j
done

# -----------------------------------------------------
#  Close file descriptors
# -----------------------------------------------------
exec 4<&-
exec 5<&-
 
Old 02-01-2008, 12:49 AM   #4
muazfarooqaslam
LQ Newbie
 
Registered: Dec 2007
Posts: 22

Original Poster
Rep: Reputation: 15
Thanks alot for all the help. Let me clear the scenario. I have a file (data.txt) as follows,

MSISDN NAME
923018559792 John
923018559791 Kyle
923008523323 Tom
923004014142 David

I assigned each column to a separate variable as follows,

MSISDN=`awk '{print $1}' data.txt`
NAME=`awk '{print $2}' data.txt`

Now i want to run a for loop on both variables in such a way that corresponding entries of both variables get out on each run of for loop, something like

for i in $MSISDN, j in $FIRST_NAME
do
echo -n Si
echo $j
done

Colucix suggested using file descripters which i have no experience of. Can somebody please elaborate a little bit more.

Thankyou
 
Old 02-01-2008, 01:28 AM   #5
Nylex
LQ Addict
 
Registered: Jul 2003
Location: London, UK
Distribution: Slackware
Posts: 7,464

Rep: Reputation: Disabled
What's wrong with using an array, as suggested? It seems like the obvious solution..
 
Old 02-01-2008, 04:41 AM   #6
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976
Quote:
Originally Posted by muazfarooqaslam View Post
Colucix suggested using file descripters which i have no experience of. Can somebody please elaborate a little bit more.
I think you have all the elements to elaborate by yourself. I would opt for the array solution: you may have a look at the Advanced Bash Scripting Guide, chapter 26. It's worth to learn for further uses.

Otherwise, depending on what you want to achieve by this script, you may consider to read the file inside the loop, i.e.
Code:
while read "line"
do
    MSISDN=$(echo $line | awk '{print $1}')
    NAME=$(echo $line | awk '{print $2}')
done < data.txt
or if you want to skip the header
Code:
while read "line"
do
    MSISDN=$(echo $line | awk '{print $1}')
    NAME=$(echo $line | awk '{print $2}')
done < <(sed '1d' data.txt)

# this is "process substitution"
# chapter 22 in ABS guide
 
Old 02-01-2008, 05:04 AM   #7
muazfarooqaslam
LQ Newbie
 
Registered: Dec 2007
Posts: 22

Original Poster
Rep: Reputation: 15
there is nothing wrong with that. In fact i didnt knew about file descriptors and reading from files in bash before. But now i do, so i will use these techniques. Instead of file descriptor it can be done even more easily like this,

Code:
#!/bin/bash
while read line
do
MSISDN=`echo $line | awk '{print $1}'`
NAME=`echo $line | awk '{print $2}'`
echo -n "$MSISDN  "
echo "$NAME"
done < numbers.txt
exit
surprisingly its not working the way Colucix suggested i.e. assigining file descriptors to variables and then callling them simultaneously in a loop,

Code:
#!/bin/bash
MSISDN=`awk '{print $1}' numbers`
NAME=`awk '{print $2}' numbers`

exec 4< <(echo "$MSISDN ")
exec 5< <(echo "$NAME ")

while read -d ' ' i <&4 && read -d ' ' j <&5
do
  echo -n $i
  echo $j
done
exec 4<&-
exec 5<&-

exit
Both &4 and &5 are not called simultaneously. First while loop is completed on &4 and then on &5.

instead of giving output as follows,

923001234567 Roger
923062001009 Adam
923018559792 John
923018559791 Kyle
923008523323 Tom
923004014142 David

its giving following output,

923001234567 923062001009 923018559792 923018559791 923008523323 923004014142Roger Adam John Kyle Tom David
 
Old 02-01-2008, 05:35 AM   #8
muazfarooqaslam
LQ Newbie
 
Registered: Dec 2007
Posts: 22

Original Poster
Rep: Reputation: 15
Hi Colucix, didnt saw your last reply before posting or else i wouldn't have copied the same methods. But can you please help me with a couple of things

1. Why following line in method # 2 not working,

Code:
while read -d ' ' i <&4 && read -d ' ' j <&5

2. When we use double input redirection character < < like used in following code lines by you. I mean what is its purpose,

Code:
done < <(sed '1d' data.txt)
and

Code:
exec 4< <(echo "$MSISDN ")

Thanks alot, i have learnt a lot of things by this conversation.
 
Old 02-01-2008, 09:03 AM   #9
colucix
LQ Guru
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,509

Rep: Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976Reputation: 1976
Quote:
surprisingly its not working the way Colucix suggested i.e. assigining file descriptors to variables and then callling them simultaneously in a loop
Not truly surprisingly. In my version I built the test variables assigning them as strings made of fields separated by space. So when I use
Code:
read -d ' '
I ask the shell to read "lines" whose delimiter is a blank space. Instead in your example, you build your variables as the output of an awk command, whose default separator is a newline character. If you strip the -d option of read (default delimiter is the newline character) your version will work in the expected way.

Moreover, note that even in your script the two descriptors are read simultaneously, but since you kept the blank space as delimiter, the entire content will be read as a single line. Actually the loop in your example is executed once!

Quote:
2. When we use double input redirection character < < like used in following code lines by you. I mean what is its purpose,
This is "process substitution". The syntax is not the double < < but
Code:
<( command )
that is, the first < sign is the usual input redirection, the second < sign is tight to the parentheses construct. The better explanation is again on the Advanced Bash Scripting Guide, chapter 22:
Quote:
Process substitution is the counterpart to command substitution. Command substitution sets a variable to the result of a command, as in dir_contents=`ls −al` or xref=$( grep word datafile). Process substitution feeds the output of a process to another process (in other words, it sends the results of a command to another command).
Quote:
Thanks alot, i have learnt a lot of things by this conversation.
You're welcome! It was a pleasure!
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How to check variables in a FOR loop? richikiki Programming 6 07-10-2006 04:57 AM
shell variables becoming zero outside the loop cool244 Programming 4 05-20-2006 04:33 PM
shell variables losing value outside while loop cool244 Programming 1 05-19-2006 11:04 AM
Bash - Getting a for loop to process variables with a space in them davee Linux - General 4 10-08-2005 12:21 PM
BASH variables getting unset outside of loop trevelluk Programming 2 03-25-2005 08:14 AM


All times are GMT -5. The time now is 02:36 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration