LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices


Reply
  Search this Thread
Old 03-19-2012, 09:03 PM   #1
xwassyx
LQ Newbie
 
Registered: Mar 2012
Location: OKC
Distribution: Tiny Core
Posts: 6

Rep: Reputation: Disabled
Load variables into an array


this is a little difficult to explain in the subject line so if its confusing im srry. but basically I have a file that has some information in it.
Quote:
adapter 0
virtual disk 0
just some stuff
physical disk 0:0
some more stuff
physical disk 0:1
physical disk 0:2
this is even more
physical disk 0:3
virtual disk 1
what even more
physical disk 1:0
physical disk 1:1
What I'm trying to do is take the relevant information in its correct format and then output that to another file, kind of like a sort if that makes sense. Here is my script so far.

Quote:
#!/bin/bash

v=0
a=0
d=0
IFS=$'\n'

grep "adapter" /root/test.txt | awk '{ print $1 }' > /tmp/test1.tmp
lineRCA=( $(wc -l /tmp/test1.tmp | awk '{ print $1}') )
while [ $a -lt $lineRCA ]
do
Adap=( $(grep "adapter" /root/test.txt) )
echo "${Adap[a]}" >> /root/test.tmp
grep "virtual" /root/test.txt | awk '{ print $1 }' > /tmp/test2.tmp
lineRCV=( $(wc -l /tmp/test2.tmp | awk '{ print $1}') )
while [ $v -lt $lineRCV ]
do
Vdisk=( $(grep "virtual" /root/test.txt) )
echo "${Vdisk[v]}" >> /root/test.tmp
grep "physical" /root/test.txt | awk '{ print $1 }' > /tmp/test3.tmp
lineRCP=( $(wc -l /tmp/test3.tmp | awk '{ print $1}') )
while [ $d -lt $lineRCP ]
do
Pdisk=( $(grep "physical" /root/test.txt) )
echo "${Pdisk[d]}" >> /root/test.tmp
((d++))
done
((v++))
done
((a++))
done
The issue is it outputs as so.
Quote:
adapter 0
virtual disk 0
physical disk 0:0
physical disk 0:1
physical disk 0:2
physical disk 0:3
physical disk 1:0
physical disk 1:1
virtual disk 1
But I need it to output like
Quote:
adapter 0
virtual disk 0
physical disk 0:0
physical disk 0:1
physical disk 0:2
physical disk 0:3
virtual disk 1
physical disk 1:0
physical disk 1:1
my theory is kinda sound but sadly not working and I'm not sure what I'm doing wrong. And yes I realise my script is not very eligant and probably caveman like but I'm still learning bash.
 
Old 03-19-2012, 11:48 PM   #2
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Let's start by putting the code in CODE tags and indenting it to make it more readable:
Code:
#!/bin/bash

v=0
a=0
d=0
IFS=$'\n'

grep "adapter" /root/test.txt | awk '{ print $1 }' > /tmp/test1.tmp
lineRCA=( $(wc -l /tmp/test1.tmp | awk '{ print $1}') )
while [ $a -lt $lineRCA ]
do
    Adap=( $(grep "adapter" /root/test.txt) )
    echo "${Adap[a]}" >> /root/test.tmp
    grep "virtual" /root/test.txt | awk '{ print $1 }' > /tmp/test2.tmp
    lineRCV=( $(wc -l /tmp/test2.tmp | awk '{ print $1}') )
    while [ $v -lt $lineRCV ]
    do
        Vdisk=( $(grep "virtual" /root/test.txt) )
        echo "${Vdisk[v]}" >> /root/test.tmp
        grep "physical" /root/test.txt | awk '{ print $1 }' > /tmp/test3.tmp
        lineRCP=( $(wc -l /tmp/test3.tmp | awk '{ print $1}') )
        while [ $d -lt $lineRCP ]
            do
            Pdisk=( $(grep "physical" /root/test.txt) )
            echo "${Pdisk[d]}" >> /root/test.tmp
            ((d++))
        done
        ((v++))
    done
    ((a++))
done
The input shown is already ordered so why not process the file line by line and use bash pattern matching to avoid all those greps and awks? Something like
Code:
#!/bin/bash

while read line
do
    case $line in
        adapter* | virtual* | physical* )
            echo "$line"
    esac
done < input.txt

Last edited by catkin; 03-19-2012 at 11:49 PM.
 
Old 03-20-2012, 12:57 AM   #3
jimtony
Member
 
Registered: Jan 2011
Location: Shanghai,China
Distribution: fedora
Posts: 73
Blog Entries: 1

Rep: Reputation: 2
You should try catkin's codes, your code is too complicated.
 
Old 03-20-2012, 07:07 AM   #4
xwassyx
LQ Newbie
 
Registered: Mar 2012
Location: OKC
Distribution: Tiny Core
Posts: 6

Original Poster
Rep: Reputation: Disabled
Red face

Quote:
Originally Posted by jimtony View Post
You should try catkin's codes, your code is too complicated.
Apologies catkin on the indents, I think that was from my copy paste. And yes I do realise that my code may be complicated thanx for the help, truly =)

Basically in my example it is already in order and it is in what I'm trying to accomplish ultimately. But the ultimate goal is to read each item into a variable, or should I say line I grep for, then be able to place those where I need.

Honestly I realise my code again is caveman like but as I already said I'm trying to learn and understand.
 
Old 03-20-2012, 07:12 AM   #5
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 15,413

Rep: Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054
do you really want to do it in bash? using perl or awk will make it much easier.
 
Old 03-20-2012, 07:14 AM   #6
xwassyx
LQ Newbie
 
Registered: Mar 2012
Location: OKC
Distribution: Tiny Core
Posts: 6

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by pan64 View Post
do you really want to do it in bash? using perl or awk will make it much easier.
Perl will create more dependencies, also as I am limited on knowledge to programming, so it may be out of my league. As far as I understand awk will load each word into a variable right? not a sentence?
 
Old 03-20-2012, 07:31 AM   #7
pan64
LQ Guru
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 15,413

Rep: Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054Reputation: 5054
both can handle associative arrays, something like this:
var[name] = value
"name" and "value" can be text
and you can implement any kind of sort function
 
Old 03-20-2012, 07:49 AM   #8
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by xwassyx View Post
Apologies catkin on the indents, I think that was from my copy paste. And yes I do realise that my code may be complicated thanx for the help, truly =)

Basically in my example it is already in order and it is in what I'm trying to accomplish ultimately. But the ultimate goal is to read each item into a variable, or should I say line I grep for, then be able to place those where I need.

Honestly I realise my code again is caveman like but as I already said I'm trying to learn and understand.
You copy-paste was fine but it needs to go in CODE tags to retain indentation -- most easily by going into Advanced editing mode and using the # button.

My suggestion could be adapted to load the data into variables. Don't know exactly what you want so this is only an idea to parse out what you might want from the lines:
Code:
#!/bin/bash

while read line
do
    case $line in
        adapter* )
            adapter_n=${line## }
        virtual* )
            virtual_n=${line## }
        physical* )
            virtual_n=${line## }
    esac
done < input.txt
 
Old 03-20-2012, 07:55 AM   #9
xwassyx
LQ Newbie
 
Registered: Mar 2012
Location: OKC
Distribution: Tiny Core
Posts: 6

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by catkin View Post
You copy-paste was fine but it needs to go in CODE tags to retain indentation -- most easily by going into Advanced editing mode and using the # button.

My suggestion could be adapted to load the data into variables. Don't know exactly what you want so this is only an idea to parse out what you might want from the lines:
Code:
#!/bin/bash

while read line
do
    case $line in
        adapter* )
            adapter_n=${line## }
        virtual* )
            virtual_n=${line## }
        physical* )
            virtual_n=${line## }
    esac
done < input.txt
Hmmm it may just work jimmy!!! basically and again this may be a long way of getting it done. I'm trying to parse the info from a log to an xml file so a can format it the way I need in an html document. LOL yes going around my elbow to get to my thumb but this may just work.
 
Old 03-20-2012, 09:06 AM   #10
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian + kde 4 / 5
Posts: 6,848

Rep: Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010
To load a seqence into an array, simply use the arr+=() syntax. Every "word" inside the brackets will be added to the array as a new element.

Alternately you can use an incrementing counter variable.

Code:
#!/bin/bash

while read line; do

	case $line in

		adapter* ) adapter+= ( "${line## }" ) ;;
		virtual* ) virtual[n1++]="${line## }" ;;
		physical* ) physical[n2++]="${line## }" ;;

	esac

done < input.txt

printf "%s\n" "${adapter[@]}" "${virtual[@]}" "${physical[@]}"
BTW, just to let you know, there's a small "gotcha" that you might encounter when using a while+read loop. If the final line doesn't end with a newline character, the sub-commands won't execute.

http://mywiki.wooledge.org/BashFAQ/0...al_newlines.21

You'll have to either ensure that the file is formatted properly first, or process the last variable value separately afterwards.
 
1 members found this post helpful.
Old 03-20-2012, 09:44 AM   #11
xwassyx
LQ Newbie
 
Registered: Mar 2012
Location: OKC
Distribution: Tiny Core
Posts: 6

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by David the H. View Post
To load a seqence into an array, simply use the arr+=() syntax. Every "word" inside the brackets will be added to the array as a new element.

Alternately you can use an incrementing counter variable.

Code:
#!/bin/bash

while read line; do

	case $line in

		adapter* ) adapter+= ( "${line## }" ) ;;
		virtual* ) virtual[n1++]="${line## }" ;;
		physical* ) physical[n2++]="${line## }" ;;

	esac

done < input.txt

printf "%s\n" "${adapter[@]}" "${virtual[@]}" "${physical[@]}"
BTW, just to let you know, there's a small "gotcha" that you might encounter when using a while+read loop. If the final line doesn't end with a newline character, the sub-commands won't execute.

http://mywiki.wooledge.org/BashFAQ/0...al_newlines.21

You'll have to either ensure that the file is formatted properly first, or process the last variable value separately afterwards.
That worked perfect you are the man!!!
 
Old 03-22-2012, 12:21 PM   #12
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian + kde 4 / 5
Posts: 6,848

Rep: Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010Reputation: 2010
By the way, here's another option for you.

bash's new (v.4+) mapfile command, and process substitution, can be used to store the output lines of a command into an array.

You can also use process substitution for things like running the array through sort.

Code:
mapfile -t adapter < <( grep '^adapter' input.txt )
mapfile -t virtual < <( grep '^virtual' input.txt )
mapfile -t physical < <( grep '^physical' input.txt )

sort < <( printf "%s\n" "${adapter[@]}" )
sort < <( printf "%s\n" "${virtual[@]}" )
sort < <( printf "%s\n" "${physical[@]}" )
Of course you can also sort the output of grep directly before sending it to mapfile.
 
Old 03-22-2012, 01:16 PM   #13
xwassyx
LQ Newbie
 
Registered: Mar 2012
Location: OKC
Distribution: Tiny Core
Posts: 6

Original Poster
Rep: Reputation: Disabled
actually I realised I was making my process way to confusing and went much simpler. Basically removed the array idea and went to the basic layout you had and output the way I need. The reason I thought I needed an array is because I was putting the data in xml tags. Which I later realised was not very sound and caused lots of issue. Simply outputting $line from the read between the tags worked beautifully.

Lesson learned stick to simple stupid.
 
  


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] Using Array variables rwallingford Linux - Newbie 4 04-26-2011 08:19 PM
PHP Accesing variables within an array LionOfGod Programming 3 03-31-2011 05:43 AM
bash: use file as input into array, parse out other variables from array using awk beeblequix Linux - General 2 11-20-2009 10:07 AM
Adding array variables together nobody123 Linux - Newbie 2 02-26-2009 04:43 PM
BASH - Array Variables Micro420 Programming 5 12-15-2006 05:49 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software

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

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