Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I what to have bash script to grep output to multiple variables but have no idea how to do that:

command |grep bla > $result1 $result2 etc...

Any ideas?

S

share|improve this question
1  
Can you give an example of the output of your command and/or grep and what you expect in each variable? Do you want each variable to have the same contents? –  Dennis Williamson Nov 4 '09 at 12:09
    
If he does, that's easy enough: command |grep bla > $result1, then $result2 = $result1, etc. –  RainyRat Nov 4 '09 at 12:23
    
@RainyRat: Except that the redirection you and the OP show doesn't work. Also, to set one variable equal to another you'd do result2=$result1. If you have a dollar sign on the LHS, that'll use indirection. –  Dennis Williamson Nov 4 '09 at 12:34
    
Hi, Sorry for the delay but today was the first notification I got for some reason. Basic example: #ls -l |grep filename filename1 filename2 filename3 Now I want filename1 to be variable1 and so forth. S –  SJN Nov 6 '09 at 12:11

4 Answers 4

use read shell builtin command

share|improve this answer

Wouldn't something like this work, too:

for BLAH in `command | grep <stuff>`
do
    echo $BLAH
done
share|improve this answer
1  
Well that will split based on the IFS variable, which by default includes spaces. Also, it will depend on the command, for example, won't work with my ping example unless you gave ping count. –  Kyle Brandt Nov 4 '09 at 13:02
    
@Kyle, I'm a little confused.. what's wrong with spaces? –  warren Nov 4 '09 at 13:17
    
It may be okay, but not if when he says 'Each result' he means each line. If can of course change the IFS variable, but then there is still the fact that you have to wait for it to finish. –  Kyle Brandt Nov 4 '09 at 13:18
    
how do you mean "wait for it to finish"? If I do a for FN in * ; do ; echo $FN ; done, it will go through one at a time and echo them for me. Same with running through each item in the output of chkconfig --list and turning them on/off based on some criterion –  warren Nov 4 '09 at 13:35
    
Well, with command sub, it has to wait for the command in $() or the backticks to complete. With the glob, I think it probably waits for the entire glob to expand, not really sure. It just doesn't matter with a commands like the examples you gave, because they happen so fast. But look at what happens with the following: for i in $(perl -e '$i=0; while ($i<10) { sleep 1; print "foo\n"; $i++; }'); do echo $i;done .. understand? –  Kyle Brandt Nov 4 '09 at 13:47

It would help if you gave some examples, but I think you might want something like:

while read line; do 
    ip=$(echo $line | egrep -o '\([0-9.]+\)'); 
    echo $ip; 
done < <(ping google.com)

You could then do multiple lines like the ip=... line. -o to grep means only the part that matched.

But really, something that supports capturing groups with the regex is better than grep I think, I would use perl.

Or, if you want each line in a variable, you probably want an array. For example:

$ while IFS= read -r arr[i++]; do :;done < <(ping google.com | grep 'bytes from')
$ echo ${arr[2]}
64 bytes from yx-in-f100.1e100.net (74.125.45.100): icmp_seq=2 ttl=55 time=63.9 ms


If you just want 'multiple assignment', the shell doesn't directly support that as far as I know. So you would:

foo=$(command | grep whatever)
bar="$foo"
baz="$foo"

If you need to do that for more than couple variables, you are probably not approacing the problem correctly, as always, best to state your end goal.

share|improve this answer
    
No need for a while loop or incrementing an index in your array example - read does arrays: IFS=$'\n' read -d '' -a arr < <(ping -c 6 google.com | grep 'bytes from') –  Dennis Williamson Nov 4 '09 at 15:23
    
Dennis: Was just trying to be a little bit 'defensive' with the script, to avoid something like this contrived example based one yours: IFS=$'\n' read -d '' -a arr < <(echo 'bytes from *' | grep 'bytes from') , where asterisk will be considered a glob, of course, could just set -f. –  Kyle Brandt Nov 4 '09 at 15:49

You need to expand on what you're trying to do.

For instance, are you trying to parse random output where you want every line that happens after a line that has the word snoopy in it?

Such a thing could be accomplished by read and case in such a way:

command | grep blah |
while
  read line
do 
  case "$line"
  in
    *snoopy*) 
            read result_after_snoopy ;

            echo "This is where I do something when I find a line with the word snoopy in it and the line that comes after"
            echo "this is what I do with the line with snoopy in it" 
            echo "$line" | cut -f3 -d%
            echo "This is what I do with the line after"
            echo "$result_after_snoopy" | md5sum
        ;;
    *woodstock*) echo "This line had woodstock in it"
        ;;
  esac
done

If you want something else, let us know!

share|improve this answer
    
"Random" doesn't mean "arbitrary". –  Dennis Williamson Nov 4 '09 at 18:09
    
I believe I specifically said "random output where you want every line that happens after a line with the word snoopy". So this example is both random and arbitrary. –  chris Nov 4 '09 at 18:41

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.