Chcę, aby użytkownik został poproszony o pytanie, a następnie udzielił odpowiedzi, która zostanie zapisana pod zmienną o nazwie i, a jeśli odpowiedź (która jest plikiem) istnieje i jest zapisywalny, czyta go i grepsuje elementy w pliku i zapisuje je w nowym. Jeśli plik nie istnieje lub użytkownik nie ma wystarczających uprawnień do tego pliku, pojawi się ostrzeżenie, program uśpi się na 3 sekundy i pętle zostaną ponownie uruchomione. Dlaczego to nie działa? Ostrzeżenie po prostu nie zniknie, podobnie jak pętla.
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
Odpowiedź
Występują błędy składniowe i logiczne.
$a=true
to tylko łańcuch, a NIE operacja porównania. Oddziel spacjami, aby porównanie miało miejsce: "$a" = true
.
Po wykonaniu tej czynności pętla w ogóle nie zostanie wprowadzona, ponieważ ustawisz a=false
z góry.
POWINIENEŚ w końcu dostać się do pętli, nie będziesz w stanie wyjść, ponieważ a
nigdy nie jest ustawione na dowolne inne niż true
, ani inny mechanizm wyjścia (np. break
).
Odpowiedź
Jak zauważyli inni, w kodzie występują błędy logiczne i składniowe. Witryna ShellCheck jest dobra do usuwania błędów składniowych.
Oto moje podejście. Mam dwie wersje kodu . Pierwsza (co wolę) nie wymaga interakcji z użytkownikiem, ale przyjmuje ścieżkę dostępu w wierszu poleceń. Druga interaktywnie prosi o ścieżkę.
Powód, dla którego pierwsza nie wyświetla interaktywnego monitu o ścieżka jest taka, że nie ma większego znaczenia, jeśli użytkownik skryptu zapisuje ścieżkę w wierszu poleceń lub w wierszu polecenia skryptu, a posiadanie znaku zachęty skryptu do nazwy ścieżki dyskwalifikuje jej użycie np. zadanie cron lub gdziekolwiek indziej, gdzie może nie być podłączony terminal.
#!/bin/sh pathname=$1 if ! grep "pattern" <$pathname >i2; then echo "Something is wrong" >&2 fi
echo
powyżej będzie wykonywane, gdy
- plik w
$pathname
nie może zostać odczytany lub - plik
i2
nie można do niego napisać lub - wzorzec nie został znaleziony w
$pathname
(różni się od twojego kodu, ale patrz poniżej) .
Komunikat o błędzie jest zapisywany jako standardowy błąd, tak jak jest to w zwyczaju w przypadku komunikatów diagnostycznych w ogóle.
Z interaktywnym monitem i opóźnieniem:
#!/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
Tutaj mamy nieskończoną pętlę, która czyta od użytkownika i przerywa pętlę, jeśli wywołanie grep
poszło dobrze. Jeśli grep
z jakiegoś powodu nie powiodło się (jeden z trzech powyższych powodów), ponownie pojawi się monit o podanie nazwy ścieżki.
Oba fragmenty kodu z osobnymi test na czytelny plik (grep
może się nie powieść, nie znajdując niczego lub nie jest w stanie zapisać w swoim pliku wyjściowym.
Najpierw nieinteraktywny wersja:
#!/bin/sh pathname=$1 if [ ! -r "$pathname" ]; then echo "Something is wrong" >&2 fi grep "pattern" <$pathname >i2
Następnie wersja interaktywna:
#!/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
Lub wersja interaktywna gdzie pętla zajmuje się tylko wprowadzaniem danych przez użytkownika i walidacją:
#!/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
Odpowiedź
Spróbuj użyć prostego przerwania, aby zatrzymać nieskończoną pętlę w następujący sposób:
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
Zmodyfikowane miejsca mają komentarze z opisem.
grep <$i >i2
zamiastcat
. Ponadto w razie potrzeby cytuj rozszerzenia zmiennych, tak jak w teście .