LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
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 10-10-2012, 04:54 PM   #1
SAbhi
Member
 
Registered: Aug 2009
Location: Bangaluru, India
Distribution: CentOS 6.5, SuSE SLED/ SLES 10.2 SP2 /11.2, Fedora 11/16
Posts: 665

Rep: Reputation: Disabled
taking awk output into a variable


Hi,

Using rhel 5 $ 6
i am trying to write a script that fetch a pattern from a command line and should print with awk,

Quote:
if [ -z $1 ] ; then
echo "some text"
else
abc=`some_command_line| grep patttern|awk '{print $1 $2 $3}'`
a=`echo $1`
b=`echo $2` and so on(I want the value from awk here and then using this abc and other variables in some other section of script)
fi
but when i am trying to get these output into the variables it shows the default value of $1 which is declared in the first line which is correct as per the linux point of view but what i need is something that i mentioned inline with the commands.

can someone help....how i get that

Last edited by SAbhi; 10-10-2012 at 04:56 PM.
 
Old 10-10-2012, 08:18 PM   #2
unSpawn
Moderator
 
Registered: May 2001
Posts: 29,415
Blog Entries: 55

Rep: Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600Reputation: 3600
Quote:
Originally Posted by SAbhi View Post
i am trying to get these output into the variables
How about using an array:
Code:
ARRAY=($(some_command|grep $1|awk '{print $1 $2 $3}'))
A=${ARRAY[0]}; B=${ARRAY[1]}; # etc, etc.
 
Old 10-11-2012, 10:06 AM   #3
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 10,007

Rep: Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192Reputation: 3192
Well it is good to see someone understood that question as it makes no sense to me at all.

Are you expecting the $1 in the awk to be the same value as the one assigned to 'a'?

And grep and awk would almost never need to be used together as awk already has regex capabilities.
 
Old 10-12-2012, 03:27 AM   #4
SAbhi
Member
 
Registered: Aug 2009
Location: Bangaluru, India
Distribution: CentOS 6.5, SuSE SLED/ SLES 10.2 SP2 /11.2, Fedora 11/16
Posts: 665

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by grail View Post
Well it is good to see someone understood that question as it makes no sense to me at all.

Are you expecting the $1 in the awk to be the same value as the one assigned to 'a'?

And grep and awk would almost never need to be used together as awk already has regex capabilities.

Great i was expecting this question here, so you got the point a bit, actually i am trying
Code:
some_command_line $1| grep pattern| awk '{ print stuf_in_question }'
like this with grep something and printing some values from awk but what i am getting is the $1 argument supplied with the command line . now if you read my problem again you should be getting what my issue is ?


well i used grep cause there are more than one result for what is gievn as the argument in the some_command thing.... i think the first reply will solve my problem at the most, got the hint what i need to do, if that didnt work will be back to you..
 
Old 10-12-2012, 03:44 AM   #5
AnanthaP
Member
 
Registered: Jul 2004
Location: Chennai, India
Posts: 952

Rep: Reputation: 217Reputation: 217Reputation: 217
awk DOES NOT RETURN the output (like a function would). The output is written to the standard output and can be redirected to a file.

A scheme might be to write $1, $2, $3 with some separator between them so that you can use the $1 etc of sed as you expect.

OK
 
Old 10-12-2012, 05:12 AM   #6
SAbhi
Member
 
Registered: Aug 2009
Location: Bangaluru, India
Distribution: CentOS 6.5, SuSE SLED/ SLES 10.2 SP2 /11.2, Fedora 11/16
Posts: 665

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by AnanthaP View Post
awk DOES NOT RETURN the output (like a function would). The output is written to the standard output and can be redirected to a file.

A scheme might be to write $1, $2, $3 with some separator between them so that you can use the $1 etc of sed as you expect.

OK
well there should be some correction in the sentence..
 
Old 10-12-2012, 09:10 AM   #7
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Quote:
Originally Posted by AnanthaP View Post
awk DOES NOT RETURN the output (like a function would). The output is written to the standard output and can be redirected to a file.
The standard output of any command can be redirected to a file, but that method is not necessary in this case. The OP used the deprecated `backticks` method to perform command substitution, which is better performed using the '$(somecommand)' notation.
The OP also used needless command substitution by doing
Code:
aVariable=`echo $someOtherVariable`
when a simple assignment of one variable to another would suffice, unless '$someOtherVariable' is a string type containing whitespace.

As someone has already pointed out, this looks like an appropriate case for the use of array variables, iff the output of the awk command contains whitespace delimited data.

--- rod.

Last edited by theNbomr; 10-12-2012 at 09:12 AM.
 
Old 10-12-2012, 10:43 AM   #8
SAbhi
Member
 
Registered: Aug 2009
Location: Bangaluru, India
Distribution: CentOS 6.5, SuSE SLED/ SLES 10.2 SP2 /11.2, Fedora 11/16
Posts: 665

Original Poster
Rep: Reputation: Disabled
Many Thanks "theNbomr" just correctly dicribed the situation, well i am trying to make my code work out, and umm yes i needless used an unappropriate substitution of variable but just to describe in a simple way what i need.

Seems the prob should be sort out by using arrays as mentioned by unSpawn. will mark the thread solved once it work out...
 
Old 10-13-2012, 10:17 AM   #9
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
How about posting some actual data, instead of giving us vague descriptions of it? The more actual detail you give us, the more likely we can give you a useful solution.

In other words, what output does your "some_command_line" give you? And what exactly do you need from it, and in what format? You don't have to include real values if they're sensitive in some way, but at least post a representative example.

Anyway, to start with at least, as grail said, you can eliminate the extra grep like this:

Code:
abc=$( some_command_line | awk '/pattern/ { print $1,$2,$3 }' )
Also, notice how I included commas in the print statement. Without them the values are concatenated into a single string. With them it will insert the output record separator character, which is a single space be default.
 
Old 10-13-2012, 12:10 PM   #10
jheengut
Member
 
Registered: Sep 2006
Location: Providence, Moka Mauritius
Distribution: Slackware, Lubuntu
Posts: 352
Blog Entries: 16

Rep: Reputation: 51
Quote:
Originally Posted by David the H. View Post
How about posting some actual data, instead of giving us vague descriptions of it? The more actual detail you give us, the more likely we can give you a useful solution.
I really agree that you post some actual data
 
Old 10-14-2012, 03:07 AM   #11
SAbhi
Member
 
Registered: Aug 2009
Location: Bangaluru, India
Distribution: CentOS 6.5, SuSE SLED/ SLES 10.2 SP2 /11.2, Fedora 11/16
Posts: 665

Original Poster
Rep: Reputation: Disabled
well this is really very useful, Thanks...

you can take it this way... my commands is fetching out some data from a customised database, let me describe it with a simple example(cant show original data):

i may be wrong not too strong in scripting...

Code:
if [ -z $1 ] ; then
echo $USAGE
  else
a=`echo $1`
abc=`data get vehicle info -id $a | awk '/car/ {print $1,$2,$3,$4 }'`
f=${abc[1]}
g=${abc[2]}    ------> I suspect am i doing this right, dont think yes!!! :(
echo "vid : $f "
echo "model : $g "
echo "Price : Rs $h "
..
..
fi
exit
These values f,g,h are used later in the script that works fine with what i am using as an alternative but need to reduce some code by using a single command i know that can be done but not sure how??

ok i made a custom thing for giving example only...The most expected output is this if i provide $1=309:

Code:
the expected Command output if not using any pattern search...

---------------------------------------------------------
 id       vid           model         price
---------------------------------------------------------
 309     3040          vista-c2      10,000,00
what i need to store $2,$3,$4 from print in f,g and h so on ... can you understand it now.

Last edited by SAbhi; 10-14-2012 at 03:27 AM.
 
Old 10-14-2012, 07:58 AM   #12
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Ok, that helps some, assuming I understand it correctly. But there are still a few things that need clarification. For example, your awk search matches the string "car", but your data example doesn't include that word.

And will there always be only a single line needed from the input, or can there be multiple entries?

Finally, just to be absolutely certain, is this a bash script, specifically, or do you want it to be portable to other shells? It makes a difference in the kinds of features we can rely on, such as arrays.

I think what I'm going to do for now, until the above is answered, is just go through the code you posted line-by-line and point out what should be improved.

And right off the bat:

a) Clean, consistent formatting makes code readable and more easily debuggable. Be liberal with whitespace; indent all your sub-commands evenly, and separate logical sections with empty lines. Add comments anywhere the code isn't completely obvious (and remember, what seems obvious to you now will not be so a year or so down the line).

Scripting With Style

Code:
if [ -z $1 ] ; then
echo $USAGE
a) When using bash or ksh, it's recommended to use [[..]] for string/file tests, and ((..)) for numerical tests. Avoid using the old [..] test unless you specifically need POSIX-style portability.

http://wiki.bash-hackers.org/commands/classictest
http://wiki.bash-hackers.org/syntax/...nal_expression
http://wiki.bash-hackers.org/syntax/arith_expr

b) QUOTE ALL OF YOUR VARIABLE SUBSTITUTIONS. You should never leave the quotes off a parameter expansion unless you explicitly want the resulting string to be word-split by the shell (globbing patterns are also 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

Code:
a=`echo $1`
a) As mentioned before, this is a completely Useless Use Of Echo. Just set one parameter directly with another, i.e. "a=$1".

b) Also as already mentioned, $(..) is highly recommended over `..`. Not that you need it here, due to point a, but you will later in your script.

c) I recommend using variable names that are more descriptive than single letters, especially for important values used multiple times in the script. A bit of extra typing up front makes reading and maintaining the code later much easier.


Code:
abc=`data get vehicle info -id $a | awk '/car/ {print $1,$2,$3,$4 }'`
f=${abc[1]}
g=${abc[2]}
a) The first line sets the command output to a single scalar variable, but the next two try to treat it as an array. Check this link for details on how to set and use arrays:

http://mywiki.wooledge.org/BashFAQ/005


Here's a corrected example using all the points given so far:

Code:
abc=( $( data get vehicle info -id "$a" | awk '/car/ {print $1,$2,$3,$4 }' ) )
f=${abc[1]}
g=${abc[2]}
c) Actually, even this isn't a completely safe technique, due to the way that the shell does word-breaking (see the links on quoting above for details). If any of the fields contain spaces or glob characters, you'll probably get improper values. To do it properly you'd need to use a read structure of some kind, preferably with a user-defined field separator.

In any case, assuming the input is always a single line we can make the above much easier and just set all the variables directly with a single read:

Code:
read -r e f g h < <( data get vehicle info -id "$a" | grep 'car' )
Note that this doesn't really address the word-splitting issue yet. I'm waiting for confirmation of the input for that, as well as the "car" keyword question.

And this does use the bash-specific process substitution. If you need to avoid that, other techniques can be supplied.

Code:
exit
The "exit" keyword alone doesn't do anything useful. The script will simply produce the exit value of the final command run. Use "exit 0" to ensure that the script exits with a "success" value.

That about covers the lesson.
Good luck!
 
1 members found this post helpful.
Old 10-15-2012, 10:03 AM   #13
SAbhi
Member
 
Registered: Aug 2009
Location: Bangaluru, India
Distribution: CentOS 6.5, SuSE SLED/ SLES 10.2 SP2 /11.2, Fedora 11/16
Posts: 665

Original Poster
Rep: Reputation: Disabled
David awesome example, many thanks...

let me also clear your questions so that other people having the same prob may found it informative.

Code:
---------------------------------------------------------
 id       vid       model         price         vtyp
---------------------------------------------------------
 309     3040      vista-c2      10,000,00      car

 310     3432      alto          2,00,000       car

 311     3567      passion plus  48,000         bike

 312     3871      kinetic-star  35,000         moped

so the data i posted in previous post is just the assumed output of the command, as far you know till now i am not too good in scripts having the basic knowledge trying to get it more...

so here the above data clears that the argument taken in the very first step can be different but i wanted it to keep one at a time..
Also i am running the script with #!/bin/bash ---> to un the script using bash shell...
so please tell me how can i make this portable so it can be run on ksh and other shells also..

one more thing if i am right the outpt of the command :
Code:
read -r e f g h < <( data get vehicle info -id "$a" | grep 'car' )

# the output should be similar to below, whereas what i need is only the values not the headers of table...can you also suggest on that..

$ echo -n "$e"

---------
 id            
---------
 309
 
Old 10-20-2012, 08:46 AM   #14
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Sorry for the late reply. My schedule has been only giving me time to pop in here on weekends recently.


To make a script fully portable, you should use #!/bin/sh as the shebang. This forces the default system shell, whatever it is, to read the script in POSIX compatibility mode. And that means that the script itself has to stick to POSIX features and stay away from any syntax that's shell-specific, such as arrays.

(Note that non-posix syntax may still treated as valid if the interpreting shell understands it, but it's not guaranteed portable unless you stick to posix.)

However, unless you expect your scripts to be ported to a system that doesn't have bash installed, a fairly rare thing these days, I say don't bother. It's more hassle than its worth usually. As long as the system provides the program specified by the shebang, and the syntax in it is valid for that program, you'll be fine.



And thanks for the revised data. Now I can see that there can be more than one line in the match, which means we need to be able to loop over the output in some way.

Which then leads to the question of what we need to do with the variables you set from it, since you say that you'll be using them later on in the script. We don't want to store multiple values in a single variable. Perhaps each column should be set to an array of its own (and subsequent code also modified to handle them)?

Also, I see there can also be multiple words per column (e.g. "passion plus"), which could make things more difficult. We need some way to clearly differentiate between the column separators and the intra-column word separators if we're to grab the correct values.

If the file were tab-delimited, say, it would be much easier, or even if you could guarantee that the column separators always use multiple spaces, while word breaks were always single spaces. But there needs to be some kind of unambiguous division between columns or else there will certainly be trouble.


In any case, the header lines should not be a problem as long as the extraction command matches the lines you want correctly. Anything that doesn't match is simply ignored. But there are also various other ways to filter them out if necessary.
 
Old 10-20-2012, 09:45 AM   #15
KenJackson
Member
 
Registered: Jul 2006
Location: Maryland, USA
Distribution: Fedora and others
Posts: 757

Rep: Reputation: 145Reputation: 145
awk amazes me. It's something I'm learning.

But no one has mentioned the -o switch that GNU grep recognizes. It might be helpful.

Here's an awkless solution that might work for you. GNU grep recognizes \s as any space character, \S as any non-space character and '+' means one or more of the preceding character. I use egrep instead of grep so I don't have to backslash the +.

In printf, the negative sign in "%-12s" means to start the string at the beginning of the twelve spaces instead of pushing it to the end.
Code:
#!/bin/sh
test -z "$1"  &&  { echo "$USAGE"; exit; }

echo '---------------------------------------------------------
 id       vid       model         price         vtyp
---------------------------------------------------------'
printf " %3s %8s     %-12s %11s      %s\n" "$1" \
   $(data get vehicle info -id "$1" | egrep -o '\S+\s+\S+\s+\S+\s+\S+')
 
  


Reply



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] Printing foremated output unto a variable using AWK Regnets1 Programming 3 03-01-2012 11:32 AM
[SOLVED] Bash; awk or sed output to variable: how keep newline at end of each output line porphyry5 Programming 3 06-10-2011 05:50 PM
Trouble storing a variable in a shell script after awk output uncle-c Linux - Newbie 3 02-08-2010 07:13 AM
passing awk output to $variable for shell script? NewnanNOC Programming 3 10-23-2008 02:08 PM
how to pipe/redirect awk output into a variable? johnpaulodonnell Linux - Newbie 2 01-25-2007 06:54 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:45 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
Open Source Consulting | Domain Registration