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
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!
$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 ]
.