LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
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


Reply
  Search this Thread
Old 05-18-2011, 10:21 AM   #1
jomann
LQ Newbie
 
Registered: Mar 2011
Posts: 24

Rep: Reputation: 0
Reading lines to an array and generate dynamic zenity list


Hi there,

first some explanation what I want to do exactly:

I have a textfile which looks for instance like this:

file.txt:
...
something=else to do
name=job one
name=job two
something=else again
whatever=dont know
name=gohome
...

I want to read all lines that starts with "name=" into an array. From this array a zenity-radiolist has to be generated. How often "name=" comes up in file.txt is variable/changes.

Regarding the upper example my zenity-radiolist shall have three choices:
job one
job two
gohome

What I've got so far:

Code:
#!/bin/bash

sfile="~/file.txt"

foo=( $(grep 'name=' $sfile))

# change IFS to linebrake to avoid problem with spaces
IFS=$'\n'     

# I want to get rid off 'name=', I want the pure job-description
# this gives a propper output:
echo ${foo[0]} | awk 'BEGIN {FS="="} {print $2}' 
echo ${foo[1]} | awk 'BEGIN {FS="="} {print $2}'
echo ${foo[3]} | awk 'BEGIN {FS="="} {print $2}'

# but how can i get rid of 'name=' permanently? How can I get my jobs into the array without the leading 'name='?

# anyway, next step would be to create the zenity-radiolist...
# I tried like this:

zenity --list --text="Show jobs:" --radiolist --column "Choice" --column "Job-name" \
TRUE ${foo[@]::1} $(printf 'FALSE %s\n' ${foo[@]::1})
From my point of view the zenity-radiolist should display the first item as checked and any other item as unchecked. It's a pity but the list shows only the first item (which indeed is checked) and no other items. Why?

So, my questions are:
1) How can I get rid of 'name=' from all items in my array or transfer the items without the leading 'name=' to a new array?
2) What is wrong with my zenity-radiolist? Why doesn't it display all items which are in my array?

Thanks a lot for any help!
Regards,
jomann.
 
Old 05-18-2011, 10:55 AM   #2
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
1) (not tested) foo=( $(grep 'name=' $sfile | sed 's/name=//' ))
2) ${foo[@]::1} may not be valid. Try replacing TRUE ${foo[@]::1} with TRUE ${foo[1]} and $(printf 'FALSE %s\n' ${foo[@]::1}) with FALSE ${foo[2]}
 
Old 05-18-2011, 11:25 AM   #3
jomann
LQ Newbie
 
Registered: Mar 2011
Posts: 24

Original Poster
Rep: Reputation: 0
Hi catkin,
thanks for the answers...

1) sed helps to cut 'name='. Perfect, thanks.

2)
Code:
zenity --list --text="Show jobs:" --radiolist --column "Choice" --column "Job-name" \
TRUE ${foo[1]} FALSE ${foo[2]}
didn't help. Result looks the same, the list is incomplete (only first item is shown).

Any other idea?

Thanks, jomann.
 
Old 05-18-2011, 01:23 PM   #4
jomann
LQ Newbie
 
Registered: Mar 2011
Posts: 24

Original Poster
Rep: Reputation: 0
I just found out that I made the mistake not to unset IFS before zenity.

But if I unset IFS the zenity-radiolist interprets the spaces in my items/jobs and too many list-items are displayed.

My code looks like this now:
Code:
#!/bin/bash

sfile="~/file.txt"

# change IFS to linebrake to avoid problem with spaces
IFS=$'\n'  

foo=( $(grep 'name=' $sfile | sed 's/name=//' ))

unset IFS

# create the zenity-radiolist...
zenity --list --text="Show jobs:" --radiolist --column "Choice" --column "Job-name" \
TRUE ${foo[@]::1} $(printf 'FALSE %s\n' ${foo[@]:1})
Result is that my list displays the following radio-choices:

job
one
job
two
gohome

which is not what I want.

Radiolist should output:
job one
job two
gohome

Any idea anybody how to tell zenity that the seperator is not the space between two words ~but the space between two array elements~?

~:-]

Thanks,
jomann.
 
Old 05-18-2011, 03:04 PM   #5
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
Quote:
Originally Posted by jomann View Post
Any idea anybody how to tell zenity that the seperator is not the space between two words ~but the space between two array elements~?
Zenity has no concept of arrays. Bash splits the array into individual arguments before passing it to the command (in this case Zenity).
 
Old 05-18-2011, 03:56 PM   #6
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
You need to quote the variable reference in order to avoid splitting it into multiple arguments, i.e. try
Code:
zenity --list --text="Show jobs:" --radiolist --column "Choice" --column "Job-name" \
TRUE "${foo[1]}" FALSE "${foo[2]}"
If you're unsure, always quote.
 
Old 05-18-2011, 04:25 PM   #7
Nominal Animal
Senior Member
 
Registered: Dec 2010
Location: Finland
Distribution: Xubuntu, CentOS, LFS
Posts: 1,723
Blog Entries: 3

Rep: Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948Reputation: 948
For the original question:

If you want to select exactly one from the list, I'd use
Code:
#!/bin/bash

OLDIFS="$IFS"
IFS="
"
choices=()
mode="true"
for name in `sed -ne 's|^[Nn][Aa][Mm][Ee][\t ]*=[\t ]*\(.*[^\t ]\)[\t ]*$|\1|p' "$@"` ; do
	choices=("${choices[@]}" "$mode" "$name")
	mode="false"
done

choice=`zenity \
	--list \
	--separator="$IFS" \
	--radiolist \
	--text="Show jobs:" \
	--column "Run" \
	--column "Job name" \
	"${choices[@]}"`
IFS="$OLDIFS"

echo "You selected '$choice'."
which as a script takes the file name containing the option list as an argument.
By default, the first job is selected.
Replace the "$@" with the job list file name, if you incorporate it into your own scripts.

Personally, I'd prefer to allow the user to select any jobs, with all selected by default:
Code:
#!/bin/bash

OLDIFS="$IFS"
IFS="
"
choices=()
for name in `sed -ne 's|^[Nn][Aa][Mm][Ee][\t ]*=[\t ]*\(.*[^\t ]\)[\t ]*$|\1|p' "$@"` ; do
	choices=("${choices[@]}" true "$name")
done

choices=(`zenity \
	--list \
	--separator="$IFS" \
	--checklist --multiple \
	--text="Show jobs:" \
	--column "Run" \
	--column "Job name" \
	"${choices[@]}"`)
IFS="$OLDIFS"

echo "You selected ${#choices[@]}: "
for choice in "${choices[@]}" ; do
	echo -e "\t'$choice'"
done
For me (zenity 2.32.0 and bash 4.1.5) the above work fine with your input.

Last edited by Nominal Animal; 05-18-2011 at 04:26 PM.
 
Old 05-19-2011, 12:09 AM   #8
catkin
LQ 5k Club
 
Registered: Dec 2008
Location: Tamil Nadu, India
Distribution: Debian
Posts: 8,578
Blog Entries: 31

Rep: Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208Reputation: 1208
Quote:
Originally Posted by Nominal Animal View Post
You need to quote the variable reference in order to avoid splitting it into multiple arguments, i.e. try
Code:
zenity --list --text="Show jobs:" --radiolist --column "Choice" --column "Job-name" \
TRUE "${foo[1]}" FALSE "${foo[2]}"
If you're unsure, always quote.
Aghh! My bad! Sorry
 
Old 05-19-2011, 01:31 AM   #9
jomann
LQ Newbie
 
Registered: Mar 2011
Posts: 24

Original Poster
Rep: Reputation: 0
Thanks a lot catkin & Nominal Animal for your help!

Finally the solution from Nominal Animal worked perfect.

CU & regards,
jomann.
 
Old 05-24-2011, 09:19 AM   #10
jomann
LQ Newbie
 
Registered: Mar 2011
Posts: 24

Original Poster
Rep: Reputation: 0
Hi all.

I have another question regarding this thread, therefore I marked this thread as "unsolved", again.

The list works perfect, once more thanks a lot. I played around with the radiolist as well as with the multiple checklist (see Nominal Animal's posting).

But now I have another question:
What if I want to add the correct status to a checklist?

Again I start with my file.txt:
...
something=else to do
name=job one
name=job two
something=else again
whatever=dont know
name=gohome
...

The code of Nominal Animal (see code below) allows to generate the perfect checklist and a selection has been done:
Code:
#!/bin/bash

OLDIFS="$IFS"
IFS="
"
choices=()
for name in `sed -ne 's|^[Nn][Aa][Mm][Ee][\t ]*=[\t ]*\(.*[^\t ]\)[\t ]*$|\1|p' "$@"` ; do
	choices=("${choices[@]}" true "$name")
done

choices=(`zenity \
	--list \
	--separator="$IFS" \
	--checklist --multiple \
	--text="Show jobs:" \
	--column "Run" \
	--column "Job name" \
	"${choices[@]}"`)
IFS="$OLDIFS"

echo "You selected ${#choices[@]}: "
for choice in "${choices[@]}" ; do
	echo -e "\t'$choice'"
done
What if I want to assign a status (TRUE/FALSE) to one or multiple of my jobs, so they are already checked or just not (regarding their current status)?

Let's say after selecting my first checklist I got a new file results.txt which looks like this:

job one=TRUE
job two=TRUE
gohome=FALSE

I thought about it but I have no clue how to get this realized?
Does anybody know & can advice how a checklist for results.txt can be coded that shows the correct status? Number of items in results.txt can vary, so the checklist needs to be dynamic, again.

Regards,
jomann.

Last edited by jomann; 05-24-2011 at 09:22 AM. Reason: edit misspelling.
 
Old 05-24-2011, 09:49 AM   #11
jomann
LQ Newbie
 
Registered: Mar 2011
Posts: 24

Original Poster
Rep: Reputation: 0
I mean something like this for obvious reason doesn't work :-)

Code:
#!/bin/bash

OLDIFS="$IFS"
IFS="
"

results1=(job one
job two
gohome)

results2=(TRUE
TRUE
FALSE)

choices=()
for r1 in "${results1[@]}" && r2 in "${results2[@]}"; do
	choices=("${choices[@]}" "$r2" "$r1")
done

choices=(`zenity \
	--list \
	--separator="$IFS" \
	--checklist --multiple \
	--text="Show jobs:" \
	--column "Run" \
	--column "Job name" \
	"${choices[@]}"`)

IFS="$OLDIFS"

I guess a loop in a loop would do the job...
Code:
for r1 in "${results1[@]}"; do
	...
	for r2 in "${results2[@]}"; do
	...
	done
done
Right? But how...???

Thx, jomann.
 
Old 05-24-2011, 10:05 AM   #12
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,983

Rep: Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182
How about:
Code:
#file.txt
something=else to do
name=job one=TRUE
name=job two=FALSE
something=else again
whatever=dont know
name=gohome=TRUE
Then we could do:
Code:
#!/bin/bash

IFS=$'\n'
NAMES=( $(awk -F= '$1 == "name"{print $3"\n"$2}' file.txt) )
unset IFS

zenity --list --text="Show jobs:" --radiolist --column "Choice" --column "Job-name" "${NAMES[@]}"
 
Old 05-24-2011, 10:14 AM   #13
jomann
LQ Newbie
 
Registered: Mar 2011
Posts: 24

Original Poster
Rep: Reputation: 0
Hi grail,

thanks a lot for your answer. I already thought about changing file.txt, too. But I get the file.txt from some other program on which I have no influance how it stores the values in file.txt. I could add TRUE/FALSE to the file somehow in dependency to some other info, but as soon as somebody works with the other program the file.txt is going to change (maybe, maybe not).

Hm... any other idea?
Can anybody make clear whether my idea with a loop in a loop would fit for my problem?

Regards,
jomann.
 
Old 05-24-2011, 10:39 AM   #14
grail
LQ Guru
 
Registered: Sep 2009
Location: Perth
Distribution: Manjaro
Posts: 9,983

Rep: Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182Reputation: 3182
Step 2:
Code:
# file2.txt
job one=TRUE
job two=TRUE
gohome=FALSE
Slight edit to script:
Code:
#!/bin/bash

IFS=$'\n'
NAMES=( $(awk -F= 'FNR == NR{if($1 == "name")names[$2]++;next}$1 in names{print $2"\n"$1}' file.txt file2.txt) )
unset IFS

zenity --list --text="Show jobs:" --radiolist --column "Choice" --column "Job-name" "${NAMES[@]}"
 
Old 05-24-2011, 11:14 AM   #15
jomann
LQ Newbie
 
Registered: Mar 2011
Posts: 24

Original Poster
Rep: Reputation: 0
grail, perfect!

strange, beautiful, simple & still impossible to code myself (...but I'm working on it).

I take off my hat off to you.
Thanks, jomann.
 
  


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
converting a for loop to an array so zenity can give progress wonderfullyrich Programming 2 03-01-2012 08:58 AM
zenity editable list help technononsense Programming 1 07-22-2010 08:36 PM
[SOLVED] how to split string into an array/list of lines in C++? rohedin Programming 11 06-06-2010 10:54 AM
How to generate option selection box using zenity........? shivarajM Linux - Software 1 04-29-2009 07:07 AM
list with dynamic array TurtleFace Programming 7 11-05-2006 06:58 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:13 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