bash: Loopar och Zenity [LÖST]

Här diskuterar vi skal, kommandon och klassiska linuxverktyg.
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

bash: Loopar och Zenity [LÖST]

Inlägg av Johnny Rosenberg »

Kan man göra någon form av loop i ett bash-skript som motsvarar do {} while i C, det vill säga där man alltid kör loopen minst ett varv och testar i slutet av loopen istället för i början?

Brukar använda zenity för användarinmatningar och man får då ett returvärde så att man kan se om användaren klickade OK eller Avsluta eller liknande. 0 betyder OK (eller Ja) och man kollar då $?-variabeln. Jag har fått för mig att detta test måste köras omedelbart efter zenity-kommandot, så det duger alltså inte att först slänga in ytterligare ett kommando dessförinnan. Stämmer detta? Och i så fall, beror det på att alla kommandon påverkar $?-variabeln?

Här är ett litet utdrag ur min kod:

Kod: Markera allt

Continue="Yes"
while [[ "$Continue" = "Yes" ]]; do
	Instrument=$(zenity --list \
		--title "Välj musikinstrument" \
		--text="Välj från listan:" \
		--column="Instrument" \
		--height=460 \
		--width=250 < "${InstrumentsList}") && \
	Musicians=$(zenity --list \
		--title "Välj musikutövare" \
		--text="Välj från listan:" \
		--column="Val" \
		--column="Instrument" \
		--checklist \
		--separator=", " \
		--height=460 \
		--width=250 < "${MusiciansList}")

	if [[ ! $? ]]; then
		Continue="No"
	fi
	echo "${Instrument}: ${Musicians}" >> "${Tempfile}"
done
Har inte testat om den fungerar än, men även om den gör det känns det lite klumpigt att behöva blanda in en extra variabel ($Continue). Någon som har en smidigare idé?

Om någon vill testa hur det ser ut ut praktiken, så ser filerna som används för att fylla dialogrutorna ut så här (filnamnen får man ju definiera själv i början), om vi börjar med InstrumentsList:

Kod: Markera allt

Accordion
Acoustic guitar
Backing vocals
Bass guitar
Boot
Cello
Digital drums
Double bass
Drum machine programming
Drums
Eggz
Harmonica
Keyboard
Keys
Lead guitar
Lead vocal
Organ
Rhythm guitar
MusiciansList ser då ut så här (bortsett från att det inte är riktiga namn här):

Kod: Markera allt

FALSE
Jeans Fullberg
FALSE
Jochny Jochnykov
FALSE
Mnuef Bertilstedt
FALSE
Knutte Nidgren
FALSE
Marika Skäggelin
FALSE
Mark Axelsten
FALSE
Mikku Söderstram
FALSE
Kulan Kulsson
FALSE
Ollurf Thygelram
FALSE
Rågur Andersgren
FALSE
Riga Krig
FALSE
Sama Grynnesson
FALSE
Sarga Landblüme
FALSE
Stafflian Öronsson
FALSE
Stephan Stephanovič
FALSE
Stenfan Redlös
FALSE
Thomus Björkstam
FALSE
Tomat Presstånk
Senast redigerad av 2 Johnny Rosenberg, redigerad totalt 19 gång.
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
ubot
Inlägg: 4613
Blev medlem: 04 jan 2008, 14:03
OS: Ubuntu
Utgåva: 24.04 Noble Numbat LTS

Re: bash: Loopar och Zenity

Inlägg av ubot »

Det är tveksamt om det finns en do-while-loop i bash. Det finns en until-loop som kanske är ett alternativ? Det går också bra att använda en if-sats i while-loopen istället för en do-while-loop:

Kod: Markera allt

#!/bin/bash
a=0
while true; do
    (( a++ ))
    echo "Value of \$a is: $a"
if [[ "$a" -ge "10" ]]; then
    echo "\$a variable is 10. Break the while-loop."
    break
fi
done
När det kommer till din while-sate med $continue Yes/No så kanske det går lika bra att testa $? direkt? Typ: while [[ "$?" != "1" ]]; do
Jag menar att du borde kunna testa $? istället för att använda Yes och No. Vad innehåller $? innan man har valt något i Zenity. Jag menar $? är 0 om du har tryckt Ok och 1 om du har tryckt Avsluta eller har jag fel? Du vill alltså fortsätta while-loopen om $? inte är 1.
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: bash: Loopar och Zenity

Inlägg av Johnny Rosenberg »

ubot skrev:Det är tveksamt om det finns en do-while-loop i bash. Det finns en until-loop som kanske är ett alternativ? Det går också bra att använda en if-sats i while-loopen istället för en do-while-loop:

Kod: Markera allt

#!/bin/bash
a=0
while true; do
    (( a++ ))
    echo "Value of \$a is: $a"
if [[ "$a" -ge "10" ]]; then
    echo "\$a variable is 10. Break the while-loop."
    break
fi
done
Tänkte inte på ”break”, faktiskt. Det är ju helt klart en möjlighet som jag missat.
ubot skrev:När det kommer till din while-sate med $continue Yes/No så kanske det går lika bra att testa $? direkt? Typ: while [[ "$?" == "0" || ! $? ]]; do
Det kanske går bra i just detta fallet, men rent generellt kan man väl inte vara helt säker på vilket värde $? har innan man kommer till loopen, eller är jag ute och cyklar? Det känns lite riskabelt, men jag kanske har fel.

Varför inte bara antingen ”while [[ "$?" == "0" ]]; do” eller ”while [[ ! $? ]]; do”? Kan inte riktigt se vad den extra eller-satsen gör för nytta, men så är jag nybörjare också, typ.
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
ubot
Inlägg: 4613
Blev medlem: 04 jan 2008, 14:03
OS: Ubuntu
Utgåva: 24.04 Noble Numbat LTS

Re: bash: Loopar och Zenity

Inlägg av ubot »

Varför inte bara antingen ”while [[ "$?" == "0" ]]; do” eller ”while [[ ! $? ]]; do”? Kan inte riktigt se vad den extra eller-satsen gör för nytta, men så är jag nybörjare också, typ.
Det såg inte jag heller. Det var därför jag uppdaterade mitt svar. Jag är ledsen att jag inte var tydligare med att jag ändrade mitt svar. Jag trodde jag skulle hinna innan du läste svaret. :)

Jag ändrade till

Kod: Markera allt

while [[ "$?" != "1" ]]; do
som jag tycker borde inträffa så länge du inte har tryckt Ok i Zenity.
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: bash: Loopar och Zenity

Inlägg av Konservburk »

Johnny Rosenberg skrev:Kan man göra någon form av loop i ett bash-skript som motsvarar do {} while i C, det vill säga där man alltid kör loopen minst ett varv och testar i slutet av loopen istället för i början?
Ja, motsvarigheten till do ... while finns. Det finns till och med hybrid-loopar där du både har kod som alltid körs minst en gång och kod som bara körs om villkoret tillåter.
Johnny Rosenberg skrev:Brukar använda zenity för användarinmatningar och man får då ett returvärde så att man kan se om användaren klickade OK eller Avsluta eller liknande. 0 betyder OK (eller Ja) och man kollar då $?-variabeln. Jag har fått för mig att detta test måste köras omedelbart efter zenity-kommandot, så det duger alltså inte att först slänga in ytterligare ett kommando dessförinnan. Stämmer detta? Och i så fall, beror det på att alla kommandon påverkar $?-variabeln?
Variabeln $? innehåller alltid returvärdet från det förra kommandot. Du måste med andra ord spara undan värdet direkt om du vill kunna använda det igen senare.

Om du bara är intresserad av ifall returvärdet är 0 eller inte 0 så går du dock över ån för att hämta vatten om du börjar titta på $? istället för att stoppa in kommandot som ett villkor i en if-sats. Operatorn && är såklart också ett vettigt alternativ.

Säg till om du vill se kodexempel på vad jag menar.
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: bash: Loopar och Zenity

Inlägg av Johnny Rosenberg »

Tack för alla svar. Jag har kommit fram till nedanstående kod som verkar fungera. Några synpunkter?

Kod: Markera allt

#!/bin/bash

# add-musician-info
# Use at your own risk
#
# Johnny Rosenberg 2010-11-18 22:42:57


# REQUIREMENTS (obviously…)
# ≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
# bash:					sudo apt-get install bash
# flac:					sudo apt-get install flac
# zenity:				sudo apt-get install zenity
# ubuntu or similar:	sudo apt-get install ubuntu (kidding… ;D )
# gedit:				sudo apt-get install gedit
#			(or use another text editor – just change the line below)
Editor="gedit"
InstrumentsList="${HOME}/.RosenTagg/Instruments"
MusiciansList="${HOME}/.RosenTagg/Musicians"
Tempfile="${HOME}/.RosenTagg/Tempfile"

if [[ $# != 1 ]]; then # Too many or too few arguments
	zenity --error 									\
		--width 300 								\
		--title "Skit bakom tangentbordet" 			\
		--text="Syntax:\n\n\tadd-musician-info FILE"
	exit 1
fi
SoundFile=$1

# Check the file. Is it a real FLAC file?
Error=$(flac -t "${SoundFile}" 2>&1 | grep error)
if [[ $Error ]]; then # Not a real FLAC file
	Message="Filen är antingen ingen FLAC-fil,\n"
	Message="${Message}eller så är den felaktig."
	zenity --error 									\
		--width 300 								\
		--title "Ogiltig fil" 						\
		--text="${Message}"
	exit 1
fi

if [[ -f ${Tempfile} ]]; then
	rm ${Tempfile}
fi
touch ${Tempfile}

Text="Välj från listan.\n"
Text="${Text}Klicka ”Avsluta” när\n"
Text="${Text}du är färdig."
while true; do
	Instrument=$(zenity --list						\
		--title "Välj musikinstrument"				\
		--text="${Text}"							\
		--column="Instrument"						\
		--height=460								\
		--width=250 < "${InstrumentsList}") &&		\
	Musicians=$(zenity --list						\
		--title "Välj musikutövare"					\
		--text="${Text}"							\
		--column="Val"								\
		--column="Instrument"						\
		--checklist									\
		--separator=", "							\
		--height=460								\
		--width=250 < "${MusiciansList}")

	if [[ $? > 0 ]]; then
		break
	fi
	echo "${Instrument}: ${Musicians}" >> "${Tempfile}"
done

$(${Editor} ${Tempfile})
Text="Din text kan nu redigeras i din\n"
Text="${Text}textredigerare. Gör eventuella\n"
Text="${Text}ändringar, spara och stäng text-\n"
Text="${Text}redigeraren.\n\n"
Text="${Text}Vill du fortsätta?\n"
zenity --question									\
	--title="Kontrollera"							\
	--text="${Text}"
if [[ $? != 0 ]]; then
	zenity --info									\
		--title="Hej då"							\
    	--text="Inga filer har ändrats."
    rm "${Tempfile}"
	exit 1
fi

Message="Vill du först rensa filen\n"
Message="${Message}från befintliga kommentarer?"
zenity --question									\
	--title="Rensa?"								\
	--text="${Message}"

if [[ $? = 0 ]]; then
	metaflac --remove-tag=DESCRIPTION "${SoundFile}"
fi

metaflac --remove-tag=COMMENT "${SoundFile}"
metaflac --remove-tag=COMMENTS "${SoundFile}"

mv "${Tempfile}" "${Tempfile}.old"
touch ${Tempfile}
while read Line; do
	echo "${Line}" | sed "s;\(.*\);DESCRIPTION=\1;" >> ${Tempfile}
done < "${Tempfile}.old"

metaflac --import-tags-from="${Tempfile}" "${SoundFile}"

rm "${Tempfile}" "${Tempfile}.old"
Givetvis måste man ändra variablerna för sökvägarna för att det ska fungera någon annanstans än här på min burk, samt att två de två textfilerna $Musicians respektive $Instruments måste existera och följa det mönster jag nämnt i tidigare inlägg i tråden.
Konservburk skrev:Operatorn && är såklart också ett vettigt alternativ.

Säg till om du vill se kodexempel på vad jag menar.
Det skulle vara intressant att se ett exempel på hur du använder &&-operatorn i en while-slinga som liknar den jag använder i mitt exempel. Eller om du har ett bättre förslag än att använda en while-slinga så är det också intressant att få ta del av. :)
ubot skrev:Det var därför jag uppdaterade mitt svar.
Hann tydligen läsa det innan du uppdaterade, men jag har sett din uppdatering nu i alla fall. :)

Och tack igen för alla berikande svar! :)
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: bash: Loopar och Zenity

Inlägg av Konservburk »

Johnny Rosenberg skrev:Tack för alla svar. Jag har kommit fram till nedanstående kod som verkar fungera. Några synpunkter?
Som jag skrev i mitt förra inlägg så går du över ån efter vatten varje gång du testar $? mot 0 direkt efter ett kommando, vilket du gör 3 gånger.
Johnny Rosenberg skrev:Det skulle vara intressant att se ett exempel på hur du använder &&-operatorn i en while-slinga som liknar den jag använder i mitt exempel.
Du själv använder ju redan operatorn && på ett ställe i while-slingan. Jag vet inte om jag kan tillföra något mer här.
Johnny Rosenberg skrev: Eller om du har ett bättre förslag än att använda en while-slinga så är det också intressant att få ta del av. :)
En slinga är bra i det här fallet. Men du skulle iofs kunna göra det snyggare och skippa det där med break och utnyttja motsvarande do-while istället.
ubot
Inlägg: 4613
Blev medlem: 04 jan 2008, 14:03
OS: Ubuntu
Utgåva: 24.04 Noble Numbat LTS

Re: bash: Loopar och Zenity

Inlägg av ubot »

En slinga är bra i det här fallet. Men du skulle iofs kunna göra det snyggare och skippa det där med break och utnyttja motsvarande do-while istället.
Han (och jag) vet ju inte hur man gör en do-while-loop i bash. :(
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: bash: Loopar och Zenity

Inlägg av Konservburk »

ubot skrev:Han (och jag) vet ju inte hur man gör en do-while-loop i bash. :(
Nu har jag inte läst regelboken, men jag skulle bli förvånad om det inte står någonting om det i den.

Jag ska gräva runt lite i den när jag har bättre med tid, ikväll eller kanske i helgen. Hittar jag inget så går jag igenom det själv i en ny tråd så att det blir lättare att hitta för andra i efterhand. Annars kan vi lika gärna ta det i den här tråden.
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: bash: Loopar och Zenity

Inlägg av Johnny Rosenberg »

Konservburk skrev:Om du bara är intresserad av ifall returvärdet är 0 eller inte 0 så går du dock över ån för att hämta vatten om du börjar titta på $? istället för att stoppa in kommandot som ett villkor i en if-sats. Operatorn && är såklart också ett vettigt alternativ.
Försökte det jag trodde att du menade men troligen missuppfattade jag totalt vad du menade, för jag fick det inte att fungera alls.
Konservburk skrev:Säg till om du vill se kodexempel på vad jag menar.
Ja tack, det vore trevligt med ett kodexempel på detta.

Sedan var det detta med do-while och jag har nu sökt igenom en del av bash-regelboken, men jag kunde inte hitta någon sådan form av loop. Märkligt, för det finns ju en until-loop, men den är ju så snarlik while-loopen att den egentligen inte behövs, men en do-while-loop hade ju faktiskt behövts. Inte för att man inte kan få det att fungera ändå, utan för att det blir betydligt elegantare kod än att gå omvägar för att få samma funktionalitet.
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
ubot
Inlägg: 4613
Blev medlem: 04 jan 2008, 14:03
OS: Ubuntu
Utgåva: 24.04 Noble Numbat LTS

Re: bash: Loopar och Zenity

Inlägg av ubot »

Så Advanced Bash-Scripting Guide är nu formellt regelboken. ;)

Jag sökte lite på Google efter do-while-loop i bash men hittade bara info om att bash inte har någon do-while-loop. Jag loggade in i IRC-kanalen #bash och frågade. Pardon my French men här är resultatet:
20:13 < realubot> How do I create a do { } while loop in bash? I mean a while loop where the first runalways will be
executed?
20:14 < greycat> The easiest way is to use while true; do ...; foo && break; done
20:14 < realubot> greycat: Isn't there any real do while loop as in PHP?
20:14 < greycat> nope
Jag tror inte det finns en do-while-loop i bash. Eller?
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: bash: Loopar och Zenity

Inlägg av Konservburk »

Johnny Rosenberg skrev:
Konservburk skrev:Om du bara är intresserad av ifall returvärdet är 0 eller inte 0 så går du dock över ån för att hämta vatten om du börjar titta på $? istället för att stoppa in kommandot som ett villkor i en if-sats. Operatorn && är såklart också ett vettigt alternativ.
Försökte det jag trodde att du menade men troligen missuppfattade jag totalt vad du menade, för jag fick det inte att fungera alls.
Konservburk skrev:Säg till om du vill se kodexempel på vad jag menar.
Ja tack, det vore trevligt med ett kodexempel på detta.
Du har kod i stil med:

Kod: Markera allt

zenity --question
if [[ $? == 0 ]]
then
   echo du svarade ja
fi

Kod: Markera allt

zenity --question
if [[ $? != 0 ]]
then
   echo du svarade nej
fi
Det jag försökte säga är att du med fördel kan ersätta den koden enligt:

Kod: Markera allt

if zenity --question
then
   echo du svarade ja
fi

Kod: Markera allt

if ! zenity --question
then
   echo du svarade nej
fi
Ett annat lika väl fungerande alternativ är att använd operatorerna && eller || som jag nämnde innan. Då blir det så här istället:

Kod: Markera allt

zenity --question && {
   echo du svarade ja
}

Kod: Markera allt

zenity --question || {
   echo du svarade nej
}
Du kan du dessutom skippa klammrarna helt om du bara har en rad kod, precis som i C:

Kod: Markera allt

zenity --question &&
   echo du svarade ja

Kod: Markera allt

zenity --question ||
   echo du svarade nej
Ställ gärna fler följdfrågor om du fortfarande inte riktigt fattar vad jag försöker förklara.
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: bash: Loopar och Zenity

Inlägg av Konservburk »

ubot skrev:Så Advanced Bash-Scripting Guide är nu formellt regelboken. ;)
Kom ihåg att det var du som sa det, inte jag. ;D
ubot skrev:Jag sökte lite på Google efter do-while-loop i bash men hittade bara info om att bash inte har någon do-while-loop. Jag loggade in i IRC-kanalen #bash och frågade. Pardon my French men här är resultatet:
20:13 < realubot> How do I create a do { } while loop in bash? I mean a while loop where the first runalways will be
executed?
20:14 < greycat> The easiest way is to use while true; do ...; foo && break; done
20:14 < realubot> greycat: Isn't there any real do while loop as in PHP?
20:14 < greycat> nope
Jag tror inte det finns en do-while-loop i bash. Eller?
Du ska inte tro på allt du hör på internet. :o
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: bash: Loopar och Zenity

Inlägg av Konservburk »

Johnny Rosenberg skrev:Sedan var det detta med do-while och jag har nu sökt igenom en del av bash-regelboken, men jag kunde inte hitta någon sådan form av loop. Märkligt, för det finns ju en until-loop, men den är ju så snarlik while-loopen att den egentligen inte behövs, men en do-while-loop hade ju faktiskt behövts. Inte för att man inte kan få det att fungera ändå, utan för att det blir betydligt elegantare kod än att gå omvägar för att få samma funktionalitet.
Nu ska vi se om jag kan förklara detta utan det blir alllför förvirrande.

En vanlig while-loop är strukturerad så här:

Kod: Markera allt

while villkor
do kommando
done
Den testar om villkor är sant och kör i så fall kommando och testar sedan villkor igen och fortsätter på det sättet tills villkor är falskt.

Motsvarigheten till en do-while-loop (som uppenbarligen är ganska okänd) är istället strukturerad så här:

Kod: Markera allt

while
   kommando
   villkor
do :
done
Den kör först kommando helt oavsett om villkor är sant eller inte. Först därefter testar den om villkor är sant och kör i så fall kommando igen och fortsätter på det sättet tills villkor är falskt.

Du kan givetvis använda hur många kommandon du vill:

Kod: Markera allt

while
   kod
   mer kod
   ännu mer kod
   villkor
do :
done
Och det fungerar förstås lika bra med until med skillnaden att villkoret blir omvänt precis som vanligt.

När det gäller den där loopen i ditt skript så skulle jag ha skrivit om den så här:

Kod: Markera allt

while
   Instrument=$(zenity --list \
      --title "Välj musikinstrument" \
      --text="${Text}" \
      --column="Instrument" \
      --height=460 \
      --width=250 < "${InstrumentsList}") &&
   Musicians=$(zenity --list \
      --title "Välj musikutövare" \
      --text="${Text}" \
      --column="Val" \
      --column="Instrument" \
      --checklist \
      --separator=", " \
      --height=460 \
      --width=250 < "${MusiciansList}")
do echo "${Instrument}: ${Musicians}" >> "${Tempfile}"
done
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: bash: Loopar och Zenity

Inlägg av Konservburk »

Jag kom förresten på en till sak som nog ingen känner till gällande loopar. Det står iaf inget om det i manualen eller i regelboken. :o

Visste ni att for-loopar kan använda vanliga klammrar istället för do och done som annars är brukligt?

Testa själva så får ni se...

Kod: Markera allt

for i in a b c
{
   echo $i
}
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: bash: Loopar och Zenity

Inlägg av Johnny Rosenberg »

Konservburk skrev:

Kod: Markera allt

if zenity --question
then
   echo du svarade ja
fi
Där satt den nog, tror jag. Kom på hur jag ska göra:

Kod: Markera allt

#!/bin/bash

Text="Klicka Ja eller Nej, men bestäm dig någon gång!"
while 	zenity --question									\
			--title="Kontrollera"							\
			--text="${Text}" &&								\
		zenity --question									\
			--title="Kontrollera"							\
			--text="${Text}"; do
	echo "Du klickade Ja båda gångerna"
done
echo "Du klickade Nej, så nu vill jag inte prata med dig mer."
Fungerar också, verkar det som.

Man tackar!
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: bash: Loopar och Zenity

Inlägg av Johnny Rosenberg »

Har nu applicerat detta i mitt lilla skript så att det nu ser ut så här istället:

Kod: Markera allt

#!/bin/bash

# add-musician-info
# Use this crap at your own risk
#
# Johnny Rosenberg 2010-11-19 21:57:48


# REQUIREMENTS (obviously…)
# ≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈≈
# bash:					sudo apt-get install bash
# flac:					sudo apt-get install flac
# zenity:				sudo apt-get install zenity
# ubuntu or similar:	sudo apt-get install ubuntu (kidding… ;D )
# gedit:				sudo apt-get install gedit
#			(or use another text editor – just change the line below)
Editor="gedit"
InstrumentsList="${HOME}/.RosenTagg/Instruments"
MusiciansList="${HOME}/.RosenTagg/Musicians"
Tempfile="${HOME}/.RosenTagg/Tempfile"

if [[ $# != 1 ]]; then # Too many or too few arguments
	zenity --error 											\
		--width 300 										\
		--title "Skit bakom tangentbordet" 					\
		--text="Syntax:\n\n\tadd-musician-info FILE"
	exit 1
fi
SoundFile=$1

# Check the file. Is it a real FLAC file?
Error=$(flac -t "${SoundFile}" 2>&1 | grep error)
if [[ $Error ]]; then # Not a real FLAC file
	Message="Filen är antingen ingen FLAC-fil,\n"
	Message="${Message}eller så är den felaktig."
	zenity --error 											\
		--width 300 										\
		--title "Ogiltig fil" 								\
		--text="${Message}"
	exit 1
fi

if [[ -f "${Tempfile}" ]]; then
	rm "${Tempfile}"
fi
touch "${Tempfile}"

Text="Välj från listan.\n"
Text="${Text}Klicka ”Avsluta” när\n"
Text="${Text}du är färdig."
while	Instrument=$(zenity --list							\
			--title "Välj musikinstrument"					\
			--text="${Text}"								\
			--column="Instrument"							\
			--height=460									\
			--width=250 < "${InstrumentsList}") &&			\
		Musicians=$(zenity --list							\
			--title "Välj musikutövare"						\
			--text="${Text}"								\
			--column="Val"									\
			--column="Instrument"							\
			--checklist										\
			--separator=", "								\
			--height=460									\
			--width=250 < "${MusiciansList}"); do
	echo "${Instrument}: ${Musicians}" >> "${Tempfile}"
done

$("${Editor}" "${Tempfile}")
Text="Din text kan nu redigeras i din\n"
Text="${Text}textredigerare. Gör eventuella\n"
Text="${Text}ändringar, spara och stäng text-\n"
Text="${Text}redigeraren.\n\n"
Text="${Text}Vill du fortsätta?\n"
if !	zenity --question									\
			--title="Kontrollera"							\
			--text="${Text}"; then
		zenity --info										\
			--title="Hej då"								\
    		--text="Inga filer har ändrats."
    	rm "${Tempfile}"
		exit 1
fi

Message="Vill du först rensa filen\n"
Message="${Message}från befintliga kommentarer?"
if	zenity --question										\
		--title="Rensa?"									\
		--text="${Message}"; then
	metaflac --remove-tag=DESCRIPTION "${SoundFile}"
fi

metaflac --remove-tag=COMMENT "${SoundFile}"
metaflac --remove-tag=COMMENTS "${SoundFile}"

mv "${Tempfile}" "${Tempfile}.old"
touch ${Tempfile}
while read Line; do
	echo "${Line}" | sed "s;\(.*\);DESCRIPTION=\1;" >> "${Tempfile}"
done < "${Tempfile}.old"

metaflac --import-tags-from="${Tempfile}" "${SoundFile}"

rm "${Tempfile}" "${Tempfile}.old"
Något annat att anmärka på i detta skript som man kan lära sig något nyttigt av? Har ju kanske inte riktigt kommit in i ”det rätta tänket” än, så jag är tacksam för alla eventuella tillrättavisningar.

Det ser i alla fall mer kompakt ut nu än innan, vilket i detta fall känns positivt.

Redigerat: Diverse stavfel, eliminerat viss inkonsekvens och lite annat…
Senast redigerad av 2 Johnny Rosenberg, redigerad totalt 19 gång.
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Användarvisningsbild
Konservburk
Inlägg: 5919
Blev medlem: 07 apr 2007, 22:28

Re: bash: Loopar och Zenity [LÖST]

Inlägg av Konservburk »

Jag tycker det ser bra ut. Det möjligtvis om du skulle vilja ha skriptet mer portabelt så att det fungerar även med /bin/sh och inte bara med /bin/bash. Det enda jag ser på rak arm som du isf måste byta ut är dubbelhakarna i dina villkor.

Edit: Du här missat citat-tecken runt ${Tempfile} på ett par ställen. Det är iofs bara ett problem om $HOME innehåller mellanrum, vilket inte är speciellt troligt, men fullt möjligt.
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: bash: Loopar och Zenity

Inlägg av Johnny Rosenberg »

Konservburk skrev:
Johnny Rosenberg skrev:Sedan var det detta med do-while och jag har nu sökt igenom en del av bash-regelboken, men jag kunde inte hitta någon sådan form av loop. Märkligt, för det finns ju en until-loop, men den är ju så snarlik while-loopen att den egentligen inte behövs, men en do-while-loop hade ju faktiskt behövts. Inte för att man inte kan få det att fungera ändå, utan för att det blir betydligt elegantare kod än att gå omvägar för att få samma funktionalitet.
Nu ska vi se om jag kan förklara detta utan det blir alllför förvirrande.

En vanlig while-loop är strukturerad så här:

Kod: Markera allt

while villkor
do kommando
done
Den testar om villkor är sant och kör i så fall kommando och testar sedan villkor igen och fortsätter på det sättet tills villkor är falskt.

Motsvarigheten till en do-while-loop (som uppenbarligen är ganska okänd) är istället strukturerad så här:

Kod: Markera allt

while
   kommando
   villkor
do :
done
Den kör först kommando helt oavsett om villkor är sant eller inte. Först därefter testar den om villkor är sant och kör i så fall kommando igen och fortsätter på det sättet tills villkor är falskt.

Du kan givetvis använda hur många kommandon du vill:

Kod: Markera allt

while
   kod
   mer kod
   ännu mer kod
   villkor
do :
done
Och det fungerar förstås lika bra med until med skillnaden att villkoret blir omvänt precis som vanligt.

När det gäller den där loopen i ditt skript så skulle jag ha skrivit om den så här:

Kod: Markera allt

while
   Instrument=$(zenity --list \
      --title "Välj musikinstrument" \
      --text="${Text}" \
      --column="Instrument" \
      --height=460 \
      --width=250 < "${InstrumentsList}") &&
   Musicians=$(zenity --list \
      --title "Välj musikutövare" \
      --text="${Text}" \
      --column="Val" \
      --column="Instrument" \
      --checklist \
      --separator=", " \
      --height=460 \
      --width=250 < "${MusiciansList}")
do echo "${Instrument}: ${Musicians}" >> "${Tempfile}"
done
Jisses, detta inlägg har jag av någon anledning helt missat! Tack för informationen! Det verkar ju lite smidigt, ska se om jag överväger att använda detta sätt istället för det jag nyss nämnde.
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Användarvisningsbild
Johnny Rosenberg
Inlägg: 1256
Blev medlem: 23 jun 2007, 16:18
OS: Ubuntu
Utgåva: 22.10 Kinetic Kudu
Kontakt:

Re: bash: Loopar och Zenity [LÖST]

Inlägg av Johnny Rosenberg »

Konservburk skrev:Jag tycker det ser bra ut. Det möjligtvis om du skulle vilja ha skriptet mer portabelt så att det fungerar även med /bin/sh och inte bara med /bin/bash. Det enda jag ser på rak arm som du isf måste byta ut är dubbelhakarna i dina villkor.

Edit: Du här missat citat-tecken runt ${Tempfile} på ett par ställen. Det är iofs bara ett problem om $HOME innehåller mellanrum, vilket inte är speciellt troligt, men fullt möjligt.
Jag tycker för min del att bash är tillräckligt portabelt och jag vill hellre lära mig fördelarna med att använda bash istället för att vara kompatibel med sh.

Jag tillhör för övrigt den kategorin (kanske är jag helt ensam här…) som blir lite frustrerad när jag hittar ett bra program och upptäcker att det även finns en version för Windows. Då brukar jag börja leta efter ett alternativ som endast funkar i Linux…

Ska kolla det där med ${Tempfile} också…
Vänliga hälsningar

Johnny Rosenberg
ジョニー・ローゼンバーグ

IEEE 1541 - binära prefix
ISO 8601 - datum och tid
Skriv svar

Återgå till "Terminalforum"