Understanding the concept behind subshells


 
Thread Tools Search this Thread
Top Forums UNIX for Dummies Questions & Answers Understanding the concept behind subshells
# 1  
Old 02-17-2014
Understanding the concept behind subshells

Can someone post a "for dummies" explanation on how subshells work?

Let's say I want to get a couple of pieces of info from the /etc/passwd file and set them as variables to be echo'd back after all data is gathered. something like
Code:
for i in ${grep 5000 /etc/passwd | cut -d : -f 5}
userid=${grep 5000 /etc/passwd | cut -d : -f 3}
last=${last -l 1 | cut -c 40-55

Now I want to make it come out as this:
Username: ____ UserID: ________ last login _________

but I think if I did this command:
echo “Username: ${i}, UserID ${userid} last login: ${last}”
it would list all usernames first, then all the user ids and then all the last logins like this:
user A
user B
user C
auser
buser
cuser
date
date
date

How would I go about getting it to put like this:
Full Name: User A Username: auser last login: date
full name user b username buser last login date?

Would I do this:
echo “Username: ${account} userid ${i}, last login:${last}”?

---------- Post updated at 03:52 PM ---------- Previous update was at 03:44 PM ----------

This is the actual code I am trying to use but it isn't working - it gives me all the full names, then all the usernames and then all the last logins:

Code:
#!/bin/bash
passfile=/etc/passwd
 
for i in  $(grep 5000 ${passfile} | cut -d : -f 5)
do
 
 
        account=$(grep 5000 /etc/passwd | cut -d : -f 3)
        username=$(grep 5000 /etc/passwd | cut -d : -f 1)
        lastlogin=$(last -l 1 | cut -c 40-55
                echo Full Name:${i} Username: ${username} User ID: ${account} Last login: ${lastlogin)
done

# 2  
Old 02-17-2014
Show your input data.
# 3  
Old 02-17-2014
It is /etc/passwd - I cannot copy that input though for some strange reason.
# 4  
Old 02-17-2014
Posting your /etc/passwd here wouldn't be a good idea.
Using several grep processes to read some fields from it is no good idea either. And assigning fields to enumerated variables can exceed the number of variables if you don't exactly know how many data lines you are going to read. Grepping for 5000 just along the line may not be specific enough; unwanted fields may fulfill this condition and give false hits.
Why don't you try sth like
Code:
while IFS=: read UN X UID GID USER REST; do echo Username: $UN, $UID, $USER; done </etc/passwd

# 5  
Old 02-17-2014
Unfortunately, that is the way I am being told to do it. I am trying to get an idea of the concept behind doing it this way.
# 6  
Old 02-18-2014
Quote:
Originally Posted by flyboynm
Unfortunately, that is the way I am being told to do it.
The way you are being told to do it is not only wasting a lot of resources but also dangerous and easily broken by unexpected (yet legal) sets of input data. RudiC was absolutely correct in his suggestion and i will try to explain the concept to you. Be prepared, though, it has absolutely nothing to do with subshells. I suggest you get yourself a good book about programming your shell (probably ksh or bash) and start reading.

Quote:
Originally Posted by RudiC
Code:
while IFS=: read UN X UID GID USER REST; do echo Username: $UN, $UID, $USER; done </etc/passwd

The shell accepts its input in "fields": parts which form distinct entities. You rely implicitly on this mechanism when you enter

Code:
grep 5000 /etc/passwd

because something has to tell the shell that "5000" is the first argument and "/etc/passwd" is the second. The reason is obvious: there is a blank in between. So, the blank character splits field1 (the first argument) from field2 (the second argument). Now consider the following:

Code:
grep "5000 /etc/passwd" /some/other/file

This will search for the string "5000 /etc/passwd" in a file named "/some/other/file". The double quotes have prevented the field splitting (or - just another way to put it - stripped from the blank character the ability to split fields). We notice that the field splitting character - the correct term is "internal field separator" or IFS for short - can be redefined.

In fact there is an environment variable "IFS", which defines the IFS character. It is possible to redefine it by simply changing its value:

Code:
IFS=X

will set the splitting character from " " to "X". Usually we want such a behavior only for a very limited part of our script (otherwiseXweXwouldXhaveXtoXuseX"X"sXinsteadXofXblanks) and fortunately it is possible to redefine the environment for only one command (this is as close to the concept of subshells as it will get). This is what RudiC did:

Code:
IFS=: read UN X UID GID USER REST

This reads a line and puts the content of field1 into variable "UN", field2 into "X", field3 into "UID", etc.. "field" now is not something sepearated by blanks but by colons - exactly the format the file /etc/passwd is written.

RudiC now put this in a while-loop to circle through all the lines in the file:

Code:
while <command> ; do
     <command1>
     <command2>
     ...
done </etc/passwd

This will execute the while-loop for as long as <command> returns "TRUE". Once it returns something else the loop is aborted. Note that the whole loop has a redirected input: it gets fed the content of /etc/passwd. This is passed to the read-command, one line for every pass of the loop. When the end of the file is reached, read will return FALSE and the loop will be aborted.

Code:
while IFS=: read UN X UID GID USER REST ; do
     echo Variable UN   holds: $UN
     echo Variable X    holds: $X
     echo Variable UID  holds: $UID
     echo Variable GID  holds: $GID
     echo Variable USER holds: $USER
     echo Variable REST holds: $REST
done </etc/passwd

Notice that all remaining parts (regardless of how many fields the line may consist of) are stored into the last variable. Try the following and notice the difference:

Code:
while IFS=: read UN X UID REST ; do
     echo Variable UN   holds: $UN
     echo Variable X    holds: $X
     echo Variable UID  holds: $UID
     echo Variable REST holds: $REST
done </etc/passwd

Once you have made sure all the variables hold the values you expect them to hold replace the echo ...-statements by some code which does whatever you want.

I hope this helps.

bakunin
 
Login or Register to Ask a Question

Previous Thread | Next Thread

9 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Export variables to subshells

So i have a script that is like this: #!/bin/sh VARA="elementary 1 elementary 2 nursery A nursery B highschool AZ" echo "${ContentOfADifferentSCRIPT}" | sh i do not have control over the script that is inside the variable "${ContentOfADifferentSCRIPT}". however, i know that the... (3 Replies)
Discussion started by: SkySmart
3 Replies

2. Shell Programming and Scripting

Errexit APPEARS set in subshells

Hi there, Everyone knows that errexit is NOT inherited by subshells. But does anyone know why errexit still appears as set with set +o? The following example highlights the fact that errexit appears set in a subshell (set +o) even though it's actually unset (it does NOT exit with false). $... (0 Replies)
Discussion started by: chebarbudo
0 Replies

3. UNIX for Dummies Questions & Answers

Confusion with the concept of wc -c and wc -m

Is wc -c and wc -m same ? Shellscript::cat file1 hello Shellscript::cat file1 | wc -c 6 Shellscript::cat file1 | wc -m 6 Shellscript::file file1 file1: ASCII text Shellscript::uname -a Linux was85host 2.6.27.45-0.1-vmi #1 SMP 2010-02-22 16:49:47 +0100 i686 i686 i386 GNU/LinuxAtleast... (5 Replies)
Discussion started by: shellscripting
5 Replies

4. UNIX for Advanced & Expert Users

Looping concept please help

Hi Gurus, Please help me in below requirement. Instance =5 (it is user parameter) total=52 (it is user parameter i need to split this to 5 and reminder as 1 instances totally 6 for example i need to splitt to each 52/5=10.4 1-10 11-20 21-30 31-40 41-50 (2 Replies)
Discussion started by: ragu.selvaraj
2 Replies

5. UNIX for Dummies Questions & Answers

Identifying the commands creating subshells

Hi all, This is the basic question. I have read many books which advised to avoid creating sub shells. e.g: use wc -l<filename rather than using cat file|wc -l. So, how to identify whether a command creates subshell or not? so,is it better to use tail -n+1 file in stead of using cat.... (3 Replies)
Discussion started by: pandeesh
3 Replies

6. Shell Programming and Scripting

Question regarding shells and subshells when a script is run

I have the following script running with nohup on one of my servers: #!/bin/bash #\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ #set log number #i=1 #\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ #Check if log exits, if so incrememnt log number up so we don't clobber #while... (8 Replies)
Discussion started by: DeCoTwc
8 Replies

7. UNIX for Dummies Questions & Answers

The Concept of thread

Hi all This is my first thread here.i confused with the concept of thread.Can anyone tell me this concept in detail.my Quation may be at primary level. Thanx in advance for help. (1 Reply)
Discussion started by: vishwasrao
1 Replies

8. UNIX for Advanced & Expert Users

semaphore concept

Hi All, I am going through the semaphore concept and have a doubt regarding the same and hope to get a resolution here. I have a file which has a number of records. I want to write an application (in C) which will be able to do concurrent read/write on these records. Of what I have... (8 Replies)
Discussion started by: maverix
8 Replies

9. Shell Programming and Scripting

Killing parent shells from subshells (KSH)

Hi all, I have a shell script which calls other shell scripts, depending on the input. Within a.sh, I have a command which calls b.sh (ie. ksh b.sh) Normally, we use the exit function to terminate a shell. However, if I choose to call exit from b.sh, I will return to the parent shell who... (4 Replies)
Discussion started by: rockysfr
4 Replies
Login or Register to Ask a Question