Oczekiwano operatora binarnego – cytując pytanie dla argumentów skryptu powłoki

Mam pytanie, w jaki sposób mogę dodawać argumenty podczas wykonywania skryptu powłoki.

Mam prosty skrypt, który pomaga mi blokować zakresy adresów IP:

~/block_ip.sh:

if [ ! $3 ] then echo "usage ~/block_ip.sh (DROP/ACCEPT) "0.0.0.0" "amsterdam"" exit 1 fi echo "adding $3" sudo iptables -I INPUT -s $2 -j $1 -m comment --comment "$3" 

Jeśli wykonam to bez argumentów, wynik będzie zgodny z oczekiwaniami:

~$ ./block_ip.sh usage ~/block_ip.sh (DROP/ACCEPT) "0.0.0.0" "amsterdam" 

Jednak spacje wydają się być przyczyną nieoczekiwane wyjście „oczekiwano operatora binarnego” :

~$ ./block_ip.sh DROP "1.0.0.0/8" "south brisbane qld" ./block_ip.sh: line 1: [: brisbane: binary operator expected adding south brisbane au 

Ale potem dodaje go pomimo nieoczekiwanego wyniku:

Chain INPUT (policy ACCEPT) num target prot opt source destination 1 DROP all -- 1.0.0.0/8 anywhere /* south brisbane au */ 

Jeśli jest to problem związany z cytowaniem, jak utworzyć argumenty (bez używania ukośników odwrotnych do zmiany spacji)? Oczywiście spodziewam się, że potrzebuję zmiany do skryptu, jest to również akceptowalne rozwiązanie.

Komentarze

  • Jeśli Twoim celem podczas testowania $3 to tylko upewnienie się, że są trzy parametry możesz użyć prostszej zmiennej powłoki $#, która przechowuje liczbę parametrów, np. if [ $# -ne 3 ].

Odpowiedź

Tak, to jest cytat problem: [ ! $3 ] rozwija się do [ ! south brisbane qld ] (cztery argumenty między [ i ]). A kiedy zobaczy cztery argumenty, z pierwszym a !, [ spodziewa się czegoś na przykład [ ! arg1 op arg2 ], gdzie op to operator binarny. (to znowu jest jedna z różnic między [ .. ] i [[ .. ]]; zobacz ten Q i również ten Q )

brisbane nie jest „ta poprawnym operatorem, więc narzeka i zwraca 2, co jest fałszywe, więc instrukcje wewnątrz if nie są wykonywane. Aby odróżnić błąd od zwykłego testu kończącego się niepowodzeniem, „trzeba by wyraźnie sprawdzić zwracaną wartość względem 2.

Z drugiej strony, jeśli $3 jest pusty, a następnie test staje się [ ! ], jednopargumentowym testem, który sprawdza, czy jedyny argument jest niepusty (to jest jednoznakowy ciąg ). W takim przypadku działa zgodnie z przeznaczeniem, choć być może nie z powodu, którego „byś oczekiwał.


Chcesz [ ! "$3" ] lub [ -z "$3" ], aby zachować ciąg jako jeden argument dla [.

Oczywiście możesz także odwrócić sens testu i wykonać rzeczywista praca wewnątrz if, tak aby błąd w teście pozwolił uniknąć uruchomienia głównych poleceń. Ale to spowodowałoby, że struktura kodu byłaby nieco bardziej niejasna.

Komentarze

  • fajnie – więc powód, dla którego to działa, jest taki, że mimo błędów, 3 $ nie jest ' t puste, więc przechodzi test !, a następnie umieszczam go w cudzysłowie w poleceniu iptables, więc jego rozwinięcie na spacje jest już obsługiwane – czy to prawda?
  • i ' chcę również zacytować parametry w wierszu iptables
  • @WEBjuju, ach tak, chciałem o tym napisać, zredagowałem, dlaczego to działa. I tak,miałeś cudzysłowy w poleceniu iptables, więc działa dobrze.
  • @ilkkachu mam cię, tak, wydaje mi się to głupie. w jakiś sposób wiedziałem o tym podświadomie, ale nie mogłem ' przekazać wiedzy do działającego rozwiązania. Jakoś sobie radziłem, nie znając tego podstawowego najemcy do tej pory, ale po prostu poważnie awansowałem. wielkie dzięki!

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *