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.
You could use xsltproc to extract the information you want. Look at an example of a very similar program in Linc Fessindon's bashpodder: http://lincgeek.org/bashpodder/
Using sed, you could use a sed like:
/<key>Name/s/<key>\(Name\)<\/key><string>\([^<]*\)<\/string>/
to select the line, extract the info and add the quotes.
The snag is that you are joining information found on separate lines. sed is a line-by-line editor. That means that you need to push the lines into the Hold buffer and pop them back when you have all three lines. Lastly remove the '\n' characters and print it out.
Start out by selecting a range of lines.
Code:
/<key>Name/,/<key>Album/{
Then inside the range, select each line you need changed:
I added the print command to test if it is working as expected so far.
Add the instructions to push the substitutions into the hold buffer. Pop the results after the last line in the range. Lastly remove the '\n' characters to join the lines, print the results. I cleared out the line buffer before exchanging, so that when you start with the next song, the hold buffer starts out empty.
Code:
#n
/<key>Name/,/<key>Album/{
/<key>Name/{
s/<key>Name<\/key><string>\([^<]*\)<\/string>/"\1",/
H
}
/<key>Artist/{
s/<key>Artist<\/key><string>\([^<]*\)<\/string>/"\1",/
H
}
/<key>Album/{
s/<key>Album<\/key><string>\([^<]*\)<\/string>/"\1"/
H
s/.*//
x
s/\n//g
p
}
}
I hadn't intended to provide the full solution, but to test and debug my test, I needed a working example. Sorry if I ruined your fun.
I did want to illustrate ranges, and subranges. Also notice how the commands are grouped. Often you need to group the commands after a match to prevent the next line being read in after certain commands. Also notice how indentation can make a sed program less "write once, read never".
I would still recommend using xsltproc instead. A sed solution is very cryptic. This is what xsltproc is designed to do.
Sorry for the late answer, I've been moving around a bit lately.
And also thanks for the answers.
Osor and ghostdog74,
Thanks for the awk. The reason I didn't I ask for awk is because I have no experience in awk. I've been using sed but it was some time ago. Ghostdog74, your solution worked. thanks. But there is something wrong with the output and I found out that not all the songs contains <key>Album</key> tags. So sometimes the result becomes:
So because there is no line for the search no and therefore CR is produced. Now, again, I'm not that great awk. Can you have if/else statement in there somewhere for echoing a CR if tag doesn't exst? I don't mind learning awk but learning by example helps...
jschiwal,
Thanks. I don't need the solution. Just the guidance. This is what I have managed to refreshing my memory and from your comments:
Code:
sed '/<key>Name<\/key>/,/<key>Album<\/key>/{
/<key>Name<\/key>/{
/<string>/,/<\/string>/{
}
}
} iTunes\ Music\ Library.xml
So all i'm lacking right not is to get the string out between the <string> tags and put it in a place holder and then 'spit it out'. H flag doesn't work. It complains about bad flag. must be version issue i guess..
After experimenting a lot, I found a solution. If anyone is interested...
I didn't realise that awk was so much simpler to use than sed for me. I develop most of the software in c and it was very similar.
Code:
/<key>Name<\/key/{
gsub(/.*<string>|<\/string>/,"")
if (/Library/){
#Playlists found. Not interesting because no more songs info exists
exit
}
else{
printf "\""$0"\","
}
artist = "false"
album = "false"
while ($0 !~ /<key>Kind<\/key>/){
getline
if (/<key>Artist<\/key>/){
gsub(/.*<string>|<\/string>/,"");printf "\""$0"\","
artist = "true"
}
if (/<key>Album<\/key>/){
if(artist == "true"){
gsub(/.*<string>|<\/string>/,"");printf "\""$0"\"\n"
}
else
{
printf "\""artist_not_found"\","
gsub(/.*<string>|<\/string>/,"");printf "\""$0"\"\n"
}
album = "true"
artist = "true"
}
}
if(album == "false"){
printf "\"album_not_found\"\n"
}
}
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.