Hogyan hurcolhatok egy if utasítást a bash-ban?

Szeretném, ha a felhasználó megkérdezne egy kérdést, majd megadná a választ, amelyet egy i nevű változó alatt tárolnak, majd ha a válasz (amely egy fájl) létezik és írható, elolvassa, felkapja a fájlban lévő dolgokat, és ezeket egy újba írja. Ha a fájl nem létezik, vagy a felhasználónak nincs elegendő jogosultsága a fájl felett, akkor figyelmeztetés jelenik meg, a program 3 másodpercig alszik, és a ciklusok újra indulnak. Miért nem működik? A figyelmeztetés egyszerűen nem tűnik el, és a hurok sem fog folytatódni.

echo "$(tput setaf 4) Tell me where the file is:" printf "\n" a=false while [ $a=true ]; do read i if [ -w $i ] then cat $i | grep stuff > i2 else a=true printf "Oh something is wrong, try again!" sleep 3 fi done 

Válasz

Szintaxis és logikai hibái vannak.

A $a=true csak egy karakterlánc, NEM összehasonlító művelet. Szétválasztva szóközökkel, így az összehasonlítás megtörténik: "$a" = true.

Ezzel a művelettel a hurok egyáltalán nem lesz megadva, ahogy beállítja a a=false előre.

KELL, hogy végre bekerülj a ciklusba, nem fogsz tudni kilépni, mivel a soha semmire nincs beállítva, csak true, és nincs más kilépési mechanizmus (pl. break).

Válasz

Amint mások rámutattak, logikai hibák és szintaxis hibák vannak a kódban. A ShellCheck webhely jó a szintaktikai hibák kiküszöbölésére.

Itt állok ezzel kapcsolatban. A kódnak két verziója van . Az elsőnek (amelyet én jobban szeretek) nincs felhasználói interakció, de egy útvonalnevet vesz fel a parancssorba. A második interaktívan kér útvonalnevet.

Az ok, amiért az első nem interaktívan kéri a Az útnév az, hogy alig van különbség, ha a szkript felhasználója írja be az útvonalnevet a parancssorba vagy a parancsfájl parancsára, és ha a parancsfájl parancssor megadja az útvonal nevét, kizárja, hogy pl. egy cron-feladat vagy bárhol máshol, ahol nem csatlakozik terminál.

#!/bin/sh pathname=$1 if ! grep "pattern" <$pathname >i2; then echo "Something is wrong" >&2 fi 

A fenti echo akkor kerül végrehajtásra, ha

  • a $pathname fájl nem olvasható, vagy
  • a nem írható, vagy
  • a minta nem található a $pathname helyen (ez eltér a kódodtól, de lásd alább) .

A hibaüzenet szabványos hibára van írva, mint általában a diagnosztikai üzeneteknél.

Interaktív felszólítással és késleltetéssel:

#!/bin/bash while true; do read -r -p "Pathname: " pathname if grep "pattern" <$pathname >i2; then break fi echo "Something is wrong" >&2 sleep 3 done 

Itt van egy végtelen ciklusunk, amely olvasható a felhasználótól és kitör a ciklusból, ha az grep hívás rendben van. Ha a grep bármilyen okból meghiúsult (a fenti három ok egyike), akkor az útvonalnév újra kéri.


Mindkét kódrész külön-külön teszt egy olvasható fájlra (a grep meghiúsulhat, ha nem talál semmit, vagy nem tud írni a kimeneti fájljába.

Először a nem interaktív verzió:

#!/bin/sh pathname=$1 if [ ! -r "$pathname" ]; then echo "Something is wrong" >&2 fi grep "pattern" <$pathname >i2 

Ezután az interaktív verzió:

#!/bin/bash while true; do read -r -p "Pathname: " pathname if [ -r "$pathname" ]; then grep "pattern" <$pathname >i2 break fi echo "Something is wrong" >&2 sleep 3 done 

Vagy egy interaktív változat ahol a hurok csak a felhasználó bevitelével és érvényesítésével foglalkozik:

#!/bin/bash while true; do read -r -p "Pathname: " pathname [ -r "$pathname" ] && break echo "Something is wrong" >&2 sleep 3 done grep "pattern" <$pathname >i2 

Válasz

Próbáld meg egyszerűen a break segítségével megállítani az ilyen végtelen ciklust:

echo "$(tput setaf 4) Tell me where the file is:" echo # This prints empty line like printf "\n" while true; do # "while true" or "while :" is infinite loop read i if [ -r $i ] # You probably mean -r (readable) and not -w (writable) then cat $i | grep stuff > i2 break # "break" ends loop else echo -n "Oh something is wrong, try again!" # "echo -n" means print without newline character sleep 3 fi done 

A módosított helyekhez megjegyzéseket fűznek leírással.

Megjegyzések

  • grep <$i >i2, nem pedig az cat. Idézze meg a változó bővítéseit is, ahol szükséges, például a tesztben .

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük