ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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.
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..
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.
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...
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:
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.
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.
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.
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).
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.
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.
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:
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.
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
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.
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+')
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.