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.
I am writing a script in order to be able to choose the stream url, among a few radio stations, so i can listen to with mplayer.
I have stations.txt text file that has one stream url per line.
stations.txt contents:
Code:
station1
station2
station3
station4
I have written so far the following bash script test.sh:
Code:
#!/bin/bash
STATIONS=()
IFS=$'\n' read -d'' -r -a STATIONS < stations.txt
cnt=${#STATIONS[@]}
for ((i=0;i<cnt;i++)); do
STATIONS[i]="$i ${STATIONS[i]}"
echo ${STATIONS[i]}
done
whiptail --title "Choose radio station:" --menu "select your choice" 16 78 5 "${STATIONS[@]}"
The problem is that whiptail, displays two stations per line and not each station in each own line, so i can select the one that i want. You can see the attached image for the visual output of the script.
What could be wrong?
By the way i'm using zsh, but i guess it doesn't matter because i include #!/bin/bash in the first line of the script. Is this true?
Thank you!
Indeed, it worked after making an array with number and description in different elements.
So, in case anyone else wants something like that this is my complete script:
1)radio.sh:
Code:
#!/bin/bash
STATIONS=()
cat stations.txt | sed 's/-/\\-/g' > stations.tmp
IFS=$'\n' read -d'' -r -a STATIONS < stations.tmp
MENUS=()
URLS=()
cnt=${#STATIONS[@]}
j=1;
for ((i=0;i<cnt;i++)); do
j=$(($i*2))
MENUS[$j]="$(($i+1))"
j=$(($i*2+1))
MENUS[$j]=$(echo ${STATIONS[$i]} | cut -d '|' -f 2)
URLS[$i]=$(echo ${STATIONS[$i]} | cut -d '|' -f 1)
done
while true
do
OPTION=$(whiptail --title Networking --menu "select your choice" 16 78 5 "${MENUS[@]}" 3>&1 1>&2 2>&3)
exitstatus=$?
if [ $exitstatus = 0 ]; then
let OPTION=$OPTION-1
echo "Playing url:" ${URLS[$OPTION]}
mplayer ${URLS[$OPTION]}
else
exit
fi
done
and stations.txt:
Code:
http://realfm.live24.gr:80/realfm | RealFM
http://legacy-100-ams.servers.mediacdn.com/maxfm93-4-patra | Max Fm
http://stream.cretanservers.gr/1045fm | Rithmos Kriti
http://netradio.live24.gr:80/melodia | Melodia
Each line in stations.txt starts with the stream url, pipe | as seperator and then the station description.
The script displays the station description only, and upon selection it launches mplayer with the apropriate url.
Thank you for your suggestions grail!.
cat-ing into a new file every time i run the script isn't very efficient or good looking code but it works.
Do you know why read doesn't "read" the whole url if it contains dashes in the first place?
Not a 100 sure on why you need to escape the dashes, but my method does not require the escaping or you could use mapfile instead of read and it also does not have issues with the dashes.
Just to be clear, my alternative replaces ALL of the original text above it, ie. the sed and the like are not needed.
actually I think it is caused because of the empty delimiter. using -d! will make it working:
Code:
IFS=$'\n' read -d! -a STATIONS < stations.txt
I do not know if it was a bug or not, but based on the man page of bash
Code:
read [-ers] [-a aname] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
One line is read from the standard input, or from the file descriptor fd supplied as an argument to the -u option, and the first word is assigned to
the first name, the second word to the second name, and so on, with leftover words and their intervening separators assigned to the last name. If
there are fewer words read from the input stream than names, the remaining names are assigned empty values. The characters in IFS are used to split
the line into words using the same rules the shell uses for expansion (described above under Word Splitting). The backslash character (\) may be
used to remove any special meaning for the next character read and for line continuation. Options, if supplied, have the following meanings:
-a aname
The words are assigned to sequential indices of the array variable aname, starting at 0. aname is unset before any new values are assigned.
Other name arguments are ignored.
-d delim
The first character of delim is used to terminate the input line, rather than newline.
empty delimiter is not supported.
to AnanthaP: s2[j]=`expr $i + 1`
do not use backticks in for cycles if not really necessary, your solution will fork a huge amount of processes (and will run therefore very slowly)
MENUS[$j]="$(($i+1))"
works much better
To capthookb: $(echo ${STATIONS[$i]} | cut -d '|' -f 2)
similar issue, it will for several processes, do not use $( ) and pipe chains if not really required (inside a loop)
use parameter substitution, see man page of bash again: echo ${STATIONS[2]% |*}
echo ${STATIONS[2]#* | }
I do not really understand: both (( $i + 1 )) and (( i + 1 )) will be evaluated by the same shell and - if I knew it well - regardless of the $ sign the result will be exactly the same. But correct me if I was wrong.
Eveluated by the same shell, but different parts of that same shell; one that is more efficient...
You can try it out with a very simple script:
Code:
#!/bin/bash
no_dollar()
{
y=0
for (( i=0 ; i<10000000 ; i++))
do
(( y=i ))
done
}
dollar()
{
y=0
for (( i=0 ; $i<10000000 ; i++ ))
do
(( y = ${i} ))
done
}
time no_dollar
sleep 2
time dollar
and you'll see the difference. To be able to see a difference, one has to iterate enough times...
On my hardware I get this output, as you can see: a bit more than 20 seconds difference in about 1 minute of runtime... that's about 30 difference. (I did not do these calculations on a machine, rather from the top of my head... they may be off!)
Code:
./performance.sh
real 0m56.921s
user 0m51.711s
sys 0m5.177s
real 1m17.051s
user 1m7.305s
sys 0m9.701s
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.