A rossz példához meg annyit, hogy, te is meg NevemTeve is a -a ill. -o hozta fel annak illusztrálására, hogy miért kell az x, holott speciel ezekhez ebben az esetben nem is kell.
Így van, akkor még nem gondoltam alaposan végig, úgy tűnt, hogy ott a -a, -o operátorok problémát okoznának. Aztán amikor a konkrét példát írtam, már javítottam, olyan értéket adtam az n változónak, amely előhozza ezt a problémát.
"Saját magadat csapod be, mert rossz példát írtál." Ha azt gondolnám amit te hiszel, hogy én gondolok, akkor lehet, hogy tényleg becsapnám magam. Semmi szükség erre a stilusra.
A rossz példához meg annyit, hogy, te is meg NevemTeve is a -a ill. -o hozta fel annak illusztrálására, hogy miért kell az x, holott speciel ezekhez ebben az esetben nem is kell.
Saját magadat csapod be, mert rossz példát írtál. Az első nem megy, hiszen így helyettesítődik:
if [ "kakukk" = "kakukk" -a -a y = "-a y" ]; then
Ez így hibás.
A második jó, hiszen:
if [ x"kakukk" = x"kakukk" -a x"-a y" = x"-a y" ]; then
A harmadik is jó:
if [ "kakukk" = "kakukk" -a "-a y" = "-a y" ]; then
A harmadikkal az a baj, hogy ebben a konkrét esetben ugyan jó, de általában nem. Nézzük ezt:
n="(" m="kakukk" if [ "$m" = "kakukk" -a "$n" = "(" ]; then echo kakukk fi
Helyettesítés után:
if [ "kakukk" = "kakukk" -a "(" = "(" ]; then
Azaz:
if [ kakukk = kakukk -a ( = ( ]; then
Ezzel az a gond, hogy a nyitó zárójelet tényleg nyitó zárójelként értelmezi, s nincs záró párja. Viszont ha odaírod az x-et - vagy szinte bármit -, akkor:
if [ xkakukk = xkakukk -a x( = x( ]; then
Az x( viszont nem olyan karakter, amitől felizgul a test, mint valami speciálisan értelmezendő dolog. Az csak egy buta string.
Ez így lehet, félreérthető. A vastagon szedett kódrész a SIGTERM-re példa. Elindítunk egy végtelen ciklust a háttérben önálló process-ként, utána várunk 5 másodpercet, majd ebből a szülő folyamatból küldünk a háttérben futónak egy SIGTERM-et, ezzel megölve azt a folyamatot.
A Ctrl-C pedig akkor lehet jó, ha az adott terminálunkban fut egy script, s meg akarjuk állítani. Persze lehet nyitni másik terminált, s onnan kinyiffantani a programunkat. Nézd meg az alábbi parancsok leírását:
Pontosan azért, mert az idézőjel egybetartotta a stringet, és -a x operátor meg nincs, tehát azt az elvártak szerint értelmezte a test. Nem ez az eset az érdekes, hanem az, amikor a változó helyére mondjuk az helyettesítődik, hogy -a.
Hát nem könnyű Veled! :) Elmagyarázom, hogy logikailag nem jó a feltétel, azt is miért, erre leírod ugyanazt valamiféle metanyelven. Mert ugye ez így a bash-nek szintaktikai hiba lesz. A shellnek nincs -o operátora. (Viszont van neki olyanja, hogy ||.)
Leírom a konstansok behelyettesítésével, hátha világos lesz.
n=elso if [ x"$n" != x"elso" -o x"$n" != x"masodik" -o x"$n" != x"harmadik" ]; then
Helyettesítés után:
n=elso if [ x"elso" != x"elso" -o x"elso" != x"masodik" -o x"elso" != x"harmadik" ]; then
Mi is lesz ez? Immáron metanyelven:
Ha ( hamis VAGY igaz VAGY igaz), akkor
Tehát
Ha (igaz), akkor
A bökkenő az, hogy ez a kifejezés a változó értékétől függetlenül mindig igaz értéket ad. Miért?
Azért, mert ha egyik konstanssal - elso, masodik, harmadik - sem egyenlő a változód - legyen mondjuk a változód értéke kilencedik -, akkor mindhárom tag értéke igaz, ezek VAGY kapcsolata igaz. Ha az egyik konstansoddal azonos a változód, az a tag ugyan hamis lesz, de ekkor a változód a másik két konstansoddal garantáltan nem egyezik, így a másik két tag igaz lesz, ezek VAGY kapcsolata szintén igaz lesz. Tehát ha a fejed tetejére állsz, akkor sem tudsz olyan változó értéket megadni ebben a kifejezésben, hogy mindhárom tag hamis legyen, s ezzel ezek VAGY kapcsolata is hamis legyen. A kifejezésed elvi hibás volt, azért nem működött. De korábbi hozzászólásomban leírtam a helyes megoldást is. :)
Ugyan nem engem kérdeztél, de azért nem elég, mert ha a $n változó mondjuk a -o stringet tartalmazza, édesmindegy, hogy idézőjelbe teszed, vagy sem, akkor oda a shell a -o stringet helyettesíti. Az idézőjel arra jó, hogy szóközök mentén ne essen szét több paraméterre a string, azaz a szóköz a string része maradjon, ne pedig a paramétereket termináló karakter.
Ebből persze nem következik, hogy mindenhova kell az idézőjel, hiszen lehet olyan, hogy azt szeretnénk, hulljon szét paraméterekre a string a szóközök mentén.
Azért konstans true a kifejezés értéke, mert ha $n bármelyik konstansoddal egyezik - pl. elso -, akkor garantáltan nem egyezik a másik kettővel. Mivel nem egyezésre vizsgálsz, azok igazak lesznek, s ezek OR kapcsolata is igaz lesz. Tehát n=elso esetén a VAGY kapcsolat első tagja false, de elso != masodik már true, ezáltal az egész kifejezés true. Az egész kifejezés csak úgy lehetne false, ha minden tagja false, az viszont sohasem teljesülhet.
A helyes megoldás az ÉS kapcsolat lenne:
if [ x"$n" != x"elso" -a x"$n" != x"masodik" -a x"$n" != x"harmadik" ]; then
Illetve De Morgan bácsit segítségül hívva:
if ! [ x"$n" = x"elso" -o x"$n" = x"masodik" -o x"$n" = x"harmadik" ]; then
Ez utóbbi alak talán közelebb áll a mindennapi gondolkodáshoz. Ha bármelyik szót eltaláltuk, az jó, tehát ennek ellenkezője esetén kell kiírnunk, hogy rossz a megadott paraméter.
Ha nagyon kegyetlenek az istenek, és az van az $x változóban, hogy -o, akkor azzal sikerülne jól összezavarni a kifejezés-kiértékelést, ha nem tennék elé egy semlegesítő prefixet (x-et).
azaz, ha beadott értéke $n-nek nem "elso" vagy nem "masodik" vagy nem "harmadik" akkor lefut a then ág. ha a beadott érték mondjuk "elso", akkor a feltétel kiértékelődése hamis lesz, hiszen nem igaz, hogy a három feltétel értékből nem egyezik valamivel, mert egyezik az "elso"-vel tehát az else ágnak kéne lefutnia nem?
a másik amire eddig nem is kérdeztem, hogy az x-et miért is kellett 'belekeverni' a feltételvizsgálatba??
További észrevételem, hogy a != valamint -o stringek a shell szempontjából nem operátorok, hanem paraméterek, amelyeket átad a [ parancsnak. A [ parancs persze mint operátort fogja értelmezni ezeket, mégpedig az alapján, hanyadik paraméterként kapta meg.
Azonban - kipróbálva a beírt mindkét if-es sort is- mindig ugyanazt a hibát kapom: "line4:[bevitt_írás_mindegymi: command not found" -ot dob.
A shell futtatásakkor ha a bevitt érték a case kitételeknek megfelel, akkor végrehajtódnak, (ugyanígy előtte azért dobja a fenti hibaüzenetet ilyenkor is) ha nem felel meg akkor ugyanazzal a hibaüzenettel nem történik semmi (holott a then ágnak végre kéne hajtódnia).
tehát valamiért az if-then téma nem tetszik neki, avagy a beolvasás nem jó neki valamiért. (a beolvasás és az if közötti kapcsolat-ra gondolok)
Próbáltam while-al, until-al mindegyiknél ugyanez a gond bármit is csinálok. Valahol a read-el lehet gond, csak megtévesztő, mert az if-es rész után a case rész ugyanakkor lefut..