LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 05-27-2009, 02:54 PM   #1
NsearchOf
LQ Newbie
 
Registered: May 2009
Posts: 8

Rep: Reputation: 0
Shell script that assign's values to fields


In need of help? I need a shell script that will read a line and assign values to each field.
Using /etc/group as an example you have

groupid:x:501:userid,userid,userid

using sed I am able to set the delimiters to a comman value e.g. a comma

Could someone show me how I could use a shell script to read each line and assign a value to each field in that line. I know how to do a fixed or static assignment but since each line in /etc/group will vary on how many fields it has I need to do some kind of loop.

output would maybe look something like this:
f1 f2 f3 f4 f5...


Note: I am VERY new to scripting! So explanations would be GREATLY appreciated.
 
Old 05-27-2009, 03:09 PM   #2
jan61
Member
 
Registered: Jun 2008
Posts: 235

Rep: Reputation: 46
Moin,

in the case of unknown number of fields you should use an array:
Code:
# redefine Input Field Separator
IFS=':
'
# now : and linefeed are field / record separator
# now read the /etc/group line per line into the array ln
getent group | while read -a ln; do
  # now print each element of the array
  for (( fld = 0; fld < ${#ln[*]}; fld++ )); do
    echo $fld ${ln[$fld]}
  done
done
Jan
 
Old 05-28-2009, 08:53 AM   #3
NsearchOf
LQ Newbie
 
Registered: May 2009
Posts: 8

Original Poster
Rep: Reputation: 0
Thank you

Thank you for your follow up. I do have one question. How to you extract information from the array. Say I wanted info from line 2 field 0 and 3?
 
Old 05-28-2009, 09:01 AM   #4
ghostdog74
Senior Member
 
Registered: Aug 2006
Posts: 2,697
Blog Entries: 5

Rep: Reputation: 241Reputation: 241Reputation: 241
you can use awk, which makes manipulating files with fields easier
Code:
awk '{print $1" is column 1, "$2" is column 2 and so on"}' file
 
Old 05-28-2009, 10:10 AM   #5
theYinYeti
Senior Member
 
Registered: Jul 2004
Location: France
Distribution: Arch Linux
Posts: 1,897

Rep: Reputation: 61
Code:
while IFS=: read usr pwd uid gid grp hom shl; do echo "user: $usr - home: $hom"; done </etc/passwd
Yves.
 
Old 05-28-2009, 03:43 PM   #6
jan61
Member
 
Registered: Jun 2008
Posts: 235

Rep: Reputation: 46
Moin,

that's not difficult:

Code:
# redefine Input Field Separator
IFS=':
'
# line number
lineno=1
# now : and linefeed are field / record separator
# now read the /etc/group line per line into the array ln
getent group | while read -a ln; do
  # access fields 0 and 3 at line 2
  if test $lineno -eq 2; then
    echo "line $lineno: field 0: ${ln[0]}; field 3: ${ln[3]}"
  fi
  # increment line number
  lineno=$((lineno + 1))
done
Jan
 
Old 05-29-2009, 08:22 AM   #7
NsearchOf
LQ Newbie
 
Registered: May 2009
Posts: 8

Original Poster
Rep: Reputation: 0
Jan61 you have been very helpful

Thank you for you help and I hate to keep bothering you. I'm still stuck on this script though. Maybe telling you want the script needs to do will help. I wanted to figure it out myself but sometimes a little help doesn't hurt. I need a script that will look at the /etc/group file and pull the group and the users that are assigned to that group in this format.
group a user1
group a user2
group a user3
group b user1
group b user2

etc...

This is a request someone gave me! Not my idea

I like your array idea and I have come close on getting information out but it's the incrementing that doesn't seem to work. Here is what I have so far. It's not pretty.

!/bin/bash
# redefine Input Field Separator
IFS=':,
'
# now : and linefeed are field / record separator
# now read the /etc/group line per line into the array ln
getent group | while read -a ln; do
# now print each element of the array
for (( fld = 0; fld < ${#ln[*]}; fld++ ));
do
x=0
y=3
z="x+2"
who=${ln[x]}
objects=${ln[z]}
echo $who $objects
done
done

The output produces the group and the second field and repeats it for however many fields there are.
I know I must be totally off using the X Y Z variables? Any ideas?
 
Old 05-29-2009, 10:09 AM   #8
GazL
Senior Member
 
Registered: May 2008
Posts: 3,503

Rep: Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026
Sometimes a little skulduggery can make the task easier when dealing with shell scripts. In the example below I use tr to convert the ',' to a space so that the for loop works correctly rather than trying to parse around the ','.

Code:
#!/bin/bash

while IFS=: read group password gid user_list
do

  for user in $(echo $user_list | tr ',' ' ')
  do
    echo group $group $user
  done

done < /etc/group
 
Old 05-29-2009, 11:00 AM   #9
NsearchOf
LQ Newbie
 
Registered: May 2009
Posts: 8

Original Poster
Rep: Reputation: 0
Thanks GazL

That seems to work! Any way you can break it down for me? I think I understand almost everything you have done but I'm not sure how you are getting the users? Is it from this statement:
read group password gid user_list
then user_list is seen as one field and then broken up by the tr statement?
 
Old 05-29-2009, 11:36 AM   #10
GazL
Senior Member
 
Registered: May 2008
Posts: 3,503

Rep: Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026
The read command will split each line of /etc/group into 4 fields delimited by colon ( because of the IFS=: ) and assign each field to one of the 4 variables listed.

The 4th field user_list will contain a comma separated list of all the users in that group. e.g. "user1,user2,user3"

The for loop is intended to be used to loop through a space separated list of values so without any changes the for would see only a single value and run just once. Within the loop $user would be "user1,user2,user3". Which is not what we want

The tr "," " " will convert
"user1,user2,user3"
to
"user1 user2 user3" which the for loop will then see as 3 separate values to loop through instead of just one.

Last edited by GazL; 05-29-2009 at 11:43 AM. Reason: fix smilyfication
 
Old 05-29-2009, 01:04 PM   #11
NsearchOf
LQ Newbie
 
Registered: May 2009
Posts: 8

Original Poster
Rep: Reputation: 0
Thanks again GazL

after replying to your last post a did more research on loops. After understanding what the for user in does. Your script made sense. Any scripting sites you recommend for newbies like me?
 
Old 05-29-2009, 01:28 PM   #12
GazL
Senior Member
 
Registered: May 2008
Posts: 3,503

Rep: Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026
Quote:
Originally Posted by NsearchOf View Post
after replying to your last post a did more research on loops. After understanding what the for user in does. Your script made sense. Any scripting sites you recommend for newbies like me?
Good stuff.


I've not really looked at any of them myself in any great detail so its hard to make a recommendation. There's some good stuff on tldp.org. If you google for 'bash tutorial' you'll find more than enough stuff too keep you in reading for a good while.
 
Old 05-29-2009, 02:03 PM   #13
jan61
Member
 
Registered: Jun 2008
Posts: 235

Rep: Reputation: 46
Moin,

now I got the point ;-) I didn't read your post carefully enough, so I didn't realize, that there's no variable list of fields in your output (the user's list has a different field delimiter than a ":").

The solution of GazL is IMHO the shortest you can get - except one line: I don't like external command calls in a loop ;-)

You can do the user list splitting using bash builtins (parameter expansion) instead of using external tr:

Code:
while IFS=: read group password gid user_list
do
  for user in ${user_list//,/ }
  do
    echo group $group $user
  done
done < /etc/group
Jan
 
Old 05-29-2009, 02:14 PM   #14
NsearchOf
LQ Newbie
 
Registered: May 2009
Posts: 8

Original Poster
Rep: Reputation: 0
Thanks Jan

How would you get the same result using an array?
 
Old 05-29-2009, 02:19 PM   #15
GazL
Senior Member
 
Registered: May 2008
Posts: 3,503

Rep: Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026Reputation: 1026
Quote:
Originally Posted by jan61 View Post

The solution of GazL is IMHO the shortest you can get - except one line: I don't like external command calls in a loop ;-)

You can do the user list splitting using bash builtins (parameter expansion) instead of using external tr:

Code:
while IFS=: read group password gid user_list
do
  for user in ${user_list//,/ }
  do
    echo group $group $user
  done
done < /etc/group
Jan

Good point jan. I should have thought of that myself.
 
  


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
Problem with shell script - pulling two fields from a file Dcrusoe Programming 6 05-15-2009 03:58 PM
bash shell script find and edit fields in a file hchoonbeng Programming 9 10-29-2008 03:13 AM
Shell Script: want to insert values in database when update script runs ring Programming 2 10-25-2007 11:48 PM
help with shell script - fill an array with values from a file delmoras Linux - General 1 07-17-2006 12:19 PM
How to change parameter values of a function in shell script? Bassam Programming 0 01-25-2004 10:52 AM


All times are GMT -5. The time now is 01:57 PM.

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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration