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 |
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.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
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.
 |
GNU/Linux Basic Guide
This 255-page guide will provide you with the keys to understand the philosophy of free software, teach you how to use and handle it, and give you the tools required to move easily in the world of GNU/Linux. Many users and administrators will be taking their first steps with this GNU/Linux Basic guide and it will show you how to approach and solve the problems you encounter.
Click Here to receive this Complete Guide absolutely free. |
|
 |
01-14-2012, 05:31 PM
|
#1
|
|
LQ Newbie
Registered: Jul 2011
Posts: 23
Rep: 
|
(BASH) How to assign 2 variables to same line?
Hello to all.
I'm trying to write a small bash funtion that retrieves Xbox Live Deal of the Week info.
Here's what i have so far:
Code:
xbox()
{
# get xbox live deals of the week game titles
xbox_name=$(curl -s http://marketplace.xbox.com/en-US/Promotion/dealoftheweek|grep -i "a class"|grep -i "title="|cut -d"\"" -f6)
# get deal prices
xbox_price=$(curl -s http://marketplace.xbox.com/en-US/Promotion/dealoftheweek|grep -i "mspoints goldprice"|cut -d">" -f3|cut -d"<" -f1)
# display info
echo -e "$xbox_name""\n$xbox_price"
}
I'm not very proficient so my method of obtaining the title and price may be a bit crude but grep and cut are tools i'm familiar with. I'd love to hear any other ways to do it.
My issue is getting the title and price on the same line. As of now, the output looks like this:
Code:
Defense Grid
Orcs Must Die!
Dungeon Defenders
South Park
400
600
800
400
I'd like it to look like this:
Code:
Defense Grid 400
Orcs Must Die! 600
Dungeon Defenders 800
South Park 400
Should i be trying to put both the title and price inside it's own variable (if so how would one achieve this?) or is there a way to echo it?
Any help is much obliged.
Last edited by Dick Dastardly; 01-14-2012 at 05:39 PM.
|
|
|
|
|
Click here to see the post LQ members have rated as the most helpful post in this thread.
|
01-14-2012, 06:56 PM
|
#2
|
|
Member
Registered: Oct 2011
Location: Oldham, UK
Distribution: Arch, Debian, LFS (debian and LFS relegated to backups)
Posts: 250
Rep:
|
This will do it:
Code:
#!/bin/bash
IFS='
'
xbox_name=($(curl -s http://marketplace.xbox.com/en-US/Promotion/dealoftheweek|grep -i "a class"|grep -i "title="|cut -d"\"" -f6))
xbox_price=($(curl -s http://marketplace.xbox.com/en-US/Promotion/dealoftheweek|grep -i "mspoints goldprice"|cut -d">" -f3|cut -d"<" -f1))
loop=${#xbox_name[*]}
for ((counter=0; counter<=$loop; counter++))
do
echo "${xbox_name[$counter]}" "${xbox_price[$counter]}"
done
"IFS=" forces bash to delimit at line breaks rather than spaces
The next two lines read name and price into arrays
loop= gets the number of array items
And the rest iterates through the array, echoing the name and corresponding price on each line.
I didn't bother looking at how you are reading the input since it seems to do the job.
Note, if you want to tabulate it like your example you'll have to play with your formatting for the echo - but I'm not doing everything for you 
Last edited by Roken; 01-14-2012 at 06:57 PM.
|
|
|
3 members found this post helpful.
|
01-14-2012, 07:22 PM
|
#3
|
|
LQ Newbie
Registered: Jul 2011
Posts: 23
Original Poster
Rep: 
|
Thanks for the solution Roken 
Been tinkering with the echo to no avail....yet!
This is what i'd assume it to be but it doesn't seem right.
Code:
echo -e "${xbox_name[$counter]}" "\t\t${xbox_price[$counter]} MSP"
|
|
|
|
01-14-2012, 08:30 PM
|
#4
|
|
Member
Registered: Oct 2011
Location: Oldham, UK
Distribution: Arch, Debian, LFS (debian and LFS relegated to backups)
Posts: 250
Rep:
|
OK, try this:
Code:
#!/bin/bash
IFS='
'
xbox_name=($(curl -s http://marketplace.xbox.com/en-US/Promotion/dealoftheweek|grep -i "a class"|grep -i "title="|cut -d"\"" -f6))
xbox_price=($(curl -s http://marketplace.xbox.com/en-US/Promotion/dealoftheweek|grep -i "mspoints goldprice"|cut -d">" -f3|cut -d"<" -f1))
loop=${#xbox_name[*]}
for ((counter=0; counter<$loop; counter++))
do
name="${xbox_name[$counter]}\t"
if [ "${#xbox_name[$counter]}" -lt 16 ]; then
name="$name\t"
fi
echo -e "$name${xbox_price[$counter]} MSP"
done
The extra test is to allow for longer names. Two tabs added for less than 16 characters, only one for more than 16 characters.
|
|
|
1 members found this post helpful.
|
01-14-2012, 09:43 PM
|
#5
|
|
LQ Newbie
Registered: Jul 2011
Posts: 23
Original Poster
Rep: 
|
Thank you a million times!
I couldn't work it out so went for this in the end (though i'll use yours now)
Code:
....
for ((counter=0; counter<="$loop"; counter++)); do
echo -e "${xbox_name[$counter]}"; echo -e "${xbox_price[$counter]} MSP"; echo
done|head -n -4
|
|
|
|
01-14-2012, 11:19 PM
|
#6
|
|
Guru
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 6,382
|
Just in case it doesn't have to be bash:
Code:
#!/usr/bin/awk -f
BEGIN{ FS = "[<>]"
OFS = "|" }
/ProductBox/{
gsub(/.*=/,"",$2)
title[++i] = $2
}
/ProductPrices/{ price[i] = $5 }
END{
for( x = 1; x <= i; x++ )
print title[x],price[x]
}
And you can run it like so for results:
Code:
$ curl -s http://marketplace.xbox.com/en-US/Promotion/dealoftheweek | ./d.awk | column -t -s "|"
"Defense Grid" 400
"Orcs Must Die!" 600
"Dungeon Defenders" 800
"South Park" 400
|
|
|
2 members found this post helpful.
|
01-15-2012, 01:35 AM
|
#7
|
|
Bash Guru
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,697
|
I'd like to point out that, for efficiency purposes, it's generally better to download the entire data set only once, and parse the saved text as needed.
Code:
xdata=$( curl -s http://marketplace.xbox.com/en-US/Promotion/dealoftheweek | grep -e "ProductBox" -e "GoldPrice" )
mapfile -t titles < <( sed -rn 's/.*title="([^"]*)".*/\1/p' <<<"$xdata" )
mapfile -t prices < <( sed -rn 's/.*GoldPrice ProductPrice">([^<]+)<.*/\1/p' <<<"$xdata" )
for i in "${!titles[@]}"; do
tabs='\t'
(( ${#titles[i]} <= 16 )) && tabs='\t\t'
printf "%s$tabs%s\n" "${titles[i]}" "${prices[i]}"
done
I used bash 4's new mapfile command to set the arrays instead of the IFS technique Roken used above, and I've simplified his loop a bit. Otherwise it's the same basic procedure. You might even want to add more tabs and more tests for them in case you get some really long tiles.
Other expressions used above (mostly bash-specific):
process substitution
here strings
the ${!array[@]} substitution pattern for listing index numbers
arithmetic evaluation
printf
Edit: I just want to say, grail's use of the column command to format the output is an excellent suggestion. You can modify the loop above to use it like this:
Code:
for i in "${!titles[@]}"; do
printf "%s|%s\n" "${titles[i]}" "${prices[i]}"
done | column -t -s '|'
Last edited by David the H.; 01-15-2012 at 01:53 AM.
Reason: as stated
|
|
|
2 members found this post helpful.
|
01-15-2012, 02:42 AM
|
#8
|
|
Guru
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 6,382
|
Nice work David  ... I will have to read up on mapfile as I tried a bash solution but suffered word splitting without setting IFS.
|
|
|
|
01-15-2012, 03:51 AM
|
#9
|
|
Bash Guru
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,697
|
Yeah, ever since I realized that mapfile could also be used internally for parsing lines from commands, I've found myself using it more and more. It can often be quite a bit less hassle than running it through a while+read loop.
Speaking of which, I'd also written up a traditional loop version that replaced the sed commands with bash regexes, but eventually decided it wasn't worth cluttering up my post with it. I guess it won't hurt to post it now, though.
Code:
tregex='title="([^"]*)"'
pregex='GoldPrice ProductPrice">([^<]+)<'
while read line; do
[[ $line =~ $tregex ]] && titles+=( "${BASH_REMATCH[1]}" )
[[ $line =~ $pregex ]] && prices+=( "${BASH_REMATCH[1]}" )
done <<<"$xdata"
Thanks in return for reminding me about column.
|
|
|
1 members found this post helpful.
|
01-15-2012, 07:27 AM
|
#10
|
|
Member
Registered: Oct 2011
Location: Oldham, UK
Distribution: Arch, Debian, LFS (debian and LFS relegated to backups)
Posts: 250
Rep:
|
Quote:
Originally Posted by David the H.
I'd like to point out that, for efficiency purposes, it's generally better to download the entire data set only once, and parse the saved text as needed.
|
I agree. As I mentioned in my original reply, I didn't really look at the data gathering code since it worked, and I assumed that this is an occasional script anyway, so not big deal re the extra download.
Having said that, mapfile and column I wasn't even aware of. Couple of new things for me to become familiar with 
|
|
|
|
01-15-2012, 09:17 AM
|
#11
|
|
LQ Newbie
Registered: Jul 2011
Posts: 23
Original Poster
Rep: 
|
Thanks for all the great info. I love the way there's always more than one way to do it.
I'll have to do a lot of reading to understand most of what you guys are telling me.
I'll have a play around and see what i come up with.
|
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -5. The time now is 11:23 PM.
|
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|