Operator binar așteptat – citând întrebarea pentru argumentele shell script

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

  • Dacă obiectivul dvs. în testare $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 ].

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!

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *