Am o întrebare despre cum adaug cuvinte atunci când execut un script shell.
Am un script simplu care mă ajută să blochez intervalele 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"
Dacă execut acest lucru fără argumente, rezultatul este așa cum era de așteptat:
~$ ./block_ip.sh usage ~/block_ip.sh (DROP/ACCEPT) "0.0.0.0" "amsterdam"
Cu toate acestea, spațiile par a fi cauza ieșire neașteptată a „operator binar așteptat” :
~$ ./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
Dar apoi o adaugă în ciuda ieșirii neașteptate:
Chain INPUT (policy ACCEPT) num target prot opt source destination 1 DROP all -- 1.0.0.0/8 anywhere /* south brisbane au */
Dacă aceasta este o problemă de citare, cum pot forma argumentele (fără a folosi bare oblice pentru a scăpa de spații)? Desigur, mă aștept să am nevoie de o schimbare pentru script, aceasta este și o soluție acceptabilă.
Comentarii
Răspuns
Da, că „este o cotare problema: [ ! $3 ]
se extinde la [ ! south brisbane qld ]
(patru argumente între [
și ]
). Și când vede patru argumente, cu primul un !
, [
așteaptă să vadă ceva ca [ ! arg1 op arg2 ]
unde op
este un operator binar. (acesta, din nou, este unul dintre lucrurile diferite între [ .. ]
și [[ .. ]]
; vezi acest Q și de asemenea, acest Q )
brisbane
nu este un operator valid, deci se plânge și returnează 2, ceea ce este fals, deci declarațiile din if
nu sunt executate. Pentru a face diferența dintre o eroare și un test nereușit obișnuit, ar trebui să testați în mod explicit valoarea returnată la 2.
Pe de altă parte, dacă $3
este gol, apoi testul devine [ ! ]
, un test cu un singur argument care verifică dacă singurul argument nu este gol (este, este șirul cu un singur caracter !
). În acest caz, funcționează conform intenției, deși poate nu din motivul pentru care te-ai aștepta.
Vrei [ ! "$3" ]
sau [ -z "$3" ]
pentru a păstra șirul ca un singur argument pentru [
.
Bineînțeles că ați putea inversa sensul testului și faceți lucru real în interiorul if
, astfel încât o eroare la test ar evita executarea comenzilor principale. Dar acest lucru ar face structura codului puțin mai clară.
Comentarii
- frumos – deci motivul pentru care funcționează atunci este că, deși greșește, $ 3 nu este ' t gol, deci trece testul! și apoi îl am citat în comanda
iptables
, astfel încât extinderea sa pentru a include spații este gestionată deja – nu-i așa? - și ei ' vreau să citez și parametrii din linia iptables
- @WEBjuju, ah da, am vrut să scriu despre asta, am editat de ce funcționează. Și da,ați avut ghilimelele în comanda
iptables
, așa că acolo funcționează bine. - @ilkkachu gotcha, da, mi se pare o prostie. cumva o știam subconștient, dar nu puteam ' să aduc cunoștințele unei soluții de lucru. Am pătruns cumva fără să cunosc acest chiriaș de bază până acum, dar tocmai m-am ridicat serios. multumesc!
$3
este doar pentru a fi sigur că există trei parametri, atunci puteți utiliza variabila shell mai simplă$#
, care deține numărul de parametri, de ex.if [ $# -ne 3 ]
.