LinuxQuestions.org
LinuxAnswers - the LQ Linux tutorial section.
Go Back   LinuxQuestions.org > Forums > Other *NIX Forums > Solaris / OpenSolaris
User Name
Password
Solaris / OpenSolaris This forum is for the discussion of Solaris and OpenSolaris.
General Sun, SunOS and Sparc related questions also go here.

Notices

Reply
 
Search this Thread
Old 03-12-2013, 01:09 AM   #1
nagendrar
Member
 
Registered: Apr 2008
Location: HYD, INDIA.
Posts: 141

Rep: Reputation: 15
print a variable out side of while read line in solaris


I write following code to update all packages in "total" variable and i will use this variable later. But i am not getting "total" value out side of loop. Please help me to solve this problem

#!/bin/sh
name=`pkginfo -i`
echo "$name" | while read LINE
do
n=`echo $LINE|awk '{print $2}'`
echo $n
total="$total $n"
done

echo $total



ThanQ,
Nagendra
 
Old 03-12-2013, 11:18 AM   #2
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris10, Solaris 11, Mint, OL
Posts: 9,493

Rep: Reputation: 355Reputation: 355Reputation: 355Reputation: 355
Use the korn shell.

The bourne shell (and bash for that matter) do not preserve the "total" variable set in your pipeline.

Code:
#!/bin/ksh
 
Old 03-12-2013, 01:06 PM   #3
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947Reputation: 1947
Please use ***[code][/code]*** tags around your code and data, to preserve the original formatting and to improve readability. Do not use quote tags, bolding, colors, "start/end" lines, or other creative techniques.


As stated, bash and most other sh-style shells run piped commands in subshells. This means any environment settings made in them are lost when the loop terminates. ksh, however, runs the final entry in the pipe chain in the main shell, and so this does work properly in it.


I set variables in a loop that's in a pipeline. Why do they disappear after the loop terminates? Or, why can't I pipe data to read?
http://mywiki.wooledge.org/BashFAQ/024


Note that bash has recently introduced a lastpipe shell option that does the same thing, but it conflicts with job management and so isn't enabled by default. It's also not recommended for interactive use because of this.

For all sh-based shells (including ksh), you can usually use some form of redirection for input instead.

Code:
while read line; do
    echo "$line"
done < <( command )
The above uses bash's process substitution feature ( ksh also has P.S. but I believe it functions slightly differently, so be sure to check the documentation). You could instead use a here document/here string with a command substitution, or a named pipe, or an external tempfile, or any other similar kind of stdin feed.


Now to give you some other script pointers (links are for bash, but the general advice is applicable to all shells).

1) When you use "!#/bin/sh" as the shebang, your script will be interpreted according to POSIX compatibility, and the use of shell-specific features becomes questionable at best. This is usually not what you want, so always be sure to explicitly state the interpreter you want to use (e.g. /bin/bash or /bin/ksh ).


2) $(..) is highly recommended over `..`. Please try to avoid using backticks. This is posix-defined and fully portable for all but the oldest shells.


3) Lists of things should never be stored in a single scalar variable, except in the case of limited, POSIX-based shells. Always use arrays if the shell supports them, or process the input directly. I assume that "pkginfo -i" produces such a list.

If the shell doesn't support arrays then you have to be much more careful in how you handle such things. See the next point for why:


4) QUOTE ALL OF YOUR VARIABLE EXPANSIONS. You should never leave the quotes off a parameter expansion unless you explicitly want the resulting string to be word-split by the shell and possible globbing patterns expanded. This is a vitally important concept in scripting, so train yourself to do it correctly now. You can learn about the exceptions later.

http://mywiki.wooledge.org/Arguments
http://mywiki.wooledge.org/WordSplitting
http://mywiki.wooledge.org/Quotes

(You're actually mostly ok here. You just missed one set, in front of the awk command.)

5) A small point: since environment variables are generally all upper-case, it's recommended practice to keep your own user variables in lower-case or mixed-case to help differentiate them.


6) You don't need awk to split a line if you know how to use read properly. Speaking of which, always use the "-r" option, to keep backslashes in the input from being interpreted.

Code:
#!/bin/ksh

while read -r _ line _; do

    echo "$line"
    total="$total $line"

done  < <( pkginfo -i )

echo "$total"
Note that the above just creates a simple list of field 2's. Is that what you want? Again, I'd suggest an array instead:

Code:
#!/bin/ksh

while read -r _ line _; do

    echo "$line"
    total+=( "$line" )

done  < <( pkginfo -i )

echo "${total[*]}"

How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?
http://mywiki.wooledge.org/BashFAQ/001

How can I use array variables?
http://mywiki.wooledge.org/BashFAQ/005/

string manipulations in bash. Most of them are portable to ksh.
 
Old 03-12-2013, 03:05 PM   #4
jlliagre
Moderator
 
Registered: Feb 2004
Location: Outside Paris
Distribution: Solaris10, Solaris 11, Mint, OL
Posts: 9,493

Rep: Reputation: 355Reputation: 355Reputation: 355Reputation: 355
Thanks David the H. for your detailed and insightful reply.

Just a small comment about this statement:
Quote:
Originally Posted by David the H. View Post
1) When you use "!#/bin/sh" as the shebang, your script will be interpreted according to POSIX compatibility, and the use of shell-specific features becomes questionable at best.
While correct with Gnu/Linux and most Unix implementations, this feature is not mandated by POSIX and doesn't apply to Solaris up to version 10 with which /bin/sh is not a POSIX compliant shell but the original Bourne shell.

POSIX actually recommend not to use any shebang at all for a compatible script to run in a POSIX environment. Under Solaris, this environment is met by having /usr/xpg4/bin first in the PATH variable.
 
  


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
[SOLVED] Read second line from file with awk and use as variable. pampers Programming 4 11-23-2012 07:50 AM
[SOLVED] Looping using while read line, using a variable instead of a file. henrtm05 Programming 3 09-24-2010 11:49 PM
How can I read some kernel variable and print it? awbodbijl Linux - Newbie 2 10-13-2008 04:52 AM
how to read certain line of file, and output to variable? jimmyjiang Red Hat 2 05-01-2007 08:46 AM
read client-side variable out of webpage jeffreybluml Linux - Newbie 2 05-23-2005 12:02 PM


All times are GMT -5. The time now is 05:37 AM.

Main Menu
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