Cum să utilizați getopts pentru a analiza opțiunile de script Linux Shell

Publicat: 2022-06-25
Un ecran de laptop care arată textul terminalului.
fatmawati achmad zaenuri/Shutterstock.com

Doriți ca scripturile dvs. Linux shell să gestioneze opțiunile și argumentele din linia de comandă mai grațios? Sistemul integrat Bash getopts vă permite să analizați opțiunile din linia de comandă cu finețe – și este, de asemenea, ușor. Vă arătăm cum.

Vă prezentăm sistemul încorporat getopts

Transmiterea de valori într-un script Bash este o chestiune destul de simplă. Vă apelați scriptul din linia de comandă sau dintr-un alt script și furnizați lista de valori în spatele numelui scriptului. Aceste valori pot fi accesate în interiorul scriptului ca variabile, începând cu $1 pentru prima variabilă, $2 pentru a doua și așa mai departe.

Dar dacă vrei să treci opțiuni unui script, situația devine rapid mai complexă. Când spunem opțiuni, ne referim la opțiunile, steagurile sau comutatoarele pe care programe precum ls le pot gestiona. Sunt precedate de o liniuță „ - ” și de obicei acționează ca un indicator al programului pentru a activa sau dezactiva un anumit aspect al funcționalității acestuia.

Cum să utilizați comanda ls pentru a lista fișiere și directoare pe Linux
LEGATE Cum să utilizați comanda ls pentru a lista fișiere și directoare pe Linux

Comanda ls are peste 50 de opțiuni, legate în principal de formatarea ieșirii sale. Opțiunea -X (sortează după extensie) sortează rezultatul alfabetic după extensia fișierului. Opțiunea -U (nesortată) listează în ordinea directorului.

Opțiunile sunt doar atât - sunt opționale. Nu știți ce opțiuni – dacă există – va alege utilizatorul să folosească și nici nu știți în ce ordine le poate enumera pe linia de comandă. Acest lucru crește complexitatea codului necesar pentru a analiza opțiunile.

Lucrurile devin și mai complicate dacă unele dintre opțiunile dvs. iau un argument, cunoscut sub numele de argument opțiune . De exemplu, opțiunea ls -w (lățime) se așteaptă să fie urmată de un număr, reprezentând lățimea maximă de afișare a ieșirii. Și, desigur, s-ar putea să treci în scriptul tău alți parametri care sunt pur și simplu valori de date, care nu sunt deloc opțiuni.

Din fericire, getopts se ocupă de această complexitate pentru tine. Și pentru că este încorporat, este disponibil pe toate sistemele care au shell-ul Bash, așa că nu este nimic de instalat.

Notă: getopts Nu getopt

Există un utilitar mai vechi numit getopt . Acesta este un mic program utilitar, nu un program încorporat. Există multe versiuni diferite de getopt cu comportamente diferite, în timp ce getops încorporat urmează liniile directoare POSIX.

 tip getopts
 tip getopt 

folosind comanda type pentru a vedea diferența dintre getop și getops

Deoarece getopt nu este o versiune încorporată, nu împărtășește unele dintre beneficiile automate pe care le are getopts , cum ar fi gestionarea rațională a spațiilor albe. Cu getopts , shell-ul Bash rulează scriptul și shell-ul Bash face analiza opțiunii. Nu trebuie să invocați un program extern pentru a gestiona analiza.

Compensația este că getopts nu tratează nume de opțiuni cu liniuțe duble și format lung. Deci, puteți utiliza opțiuni formatate ca -w , dar nu „ ---wide-format ”. Pe de altă parte, dacă aveți un script care acceptă opțiunile -a , -b și -c , getopts vă permite să le combinați ca -abc , -bca , sau -bac și așa mai departe.

Discutăm și demonstrăm getopts în acest articol, așa că asigurați-vă că adăugați „s” final la numele comenzii.

LEGATE: Cum să evadați din spațiile din căile fișierelor de pe linia de comandă Windows

O recapitulare rapidă: gestionarea valorilor parametrilor

Acest script nu folosește opțiuni întrerupte precum -a sau -b . Acceptă parametri „normali” pe linia de comandă și aceștia sunt accesați în interiorul scriptului ca valori.

 #!/bin/bash

# obțineți variabilele una câte una
echo „Variabila unu: $1” 
echo „Variabila 2: $2” 
echo „Variabila trei: $3”

# buclă prin variabile
pentru var în „ $@” do
ecou „$ var” 
Terminat

Parametrii sunt accesați în interiorul scriptului ca variabile $1 , $2 sau $3 .

Copiați acest text într-un editor și salvați-l ca fișier numit „variables.sh”. Va trebui să îl facem executabil cu comanda chmod . Va trebui să faceți acest pas pentru toate scripturile pe care le discutăm. Doar înlocuiți numele fișierului script corespunzător de fiecare dată.

 chmod +x variabile.sh 

folosind comanda chmod pentru a face un script executabil

Dacă rulăm scriptul nostru fără parametri, obținem această ieșire.

 ./variabile.sh 

rulează un script fără parametri

Nu am trecut niciun parametri, așa că scriptul nu are valori de raportat. Să oferim de data aceasta câțiva parametri.

 ./variables.sh cum să faci toci 

rulează un script cu trei cuvinte ca parametri

După cum era de așteptat, variabilele $1 , $2 și $3 au fost setate la valorile parametrilor și le vedem tipărite.

Acest tip de manipulare a parametrilor unu-la-unu înseamnă că trebuie să știm dinainte câți parametri vor exista. Buclei din partea de jos a scriptului nu-i pasă de câți parametri există, îi trece întotdeauna în buclă pe toți.

Dacă oferim un al patrulea parametru, acesta nu este atribuit unei variabile, dar bucla îl gestionează în continuare.

 ./variables.sh cum să faci site-ul tocilar 

trecând patru parametri unui script care poate gestiona doar trei

Dacă punem ghilimele în jurul a două dintre cuvinte, acestea sunt tratate ca un parametru.

 ./variables.sh cum „să faci tocilar” 

citarea a doi parametri ai liniei de comandă pentru a le trata ca un singur parametru

Dacă vom avea nevoie de scriptul nostru pentru a gestiona toate combinațiile de opțiuni, opțiuni cu argumente și parametrii de tip de date „normali”, va trebui să separăm opțiunile de parametrii obișnuiți. Putem realiza acest lucru plasând toate opțiunile - cu sau fără argumente - înaintea parametrilor obișnuiți.

Dar să nu alergăm înainte să putem merge. Să ne uităm la cel mai simplu caz pentru gestionarea opțiunilor din linia de comandă.

Opțiuni de manipulare

Folosim getopts într-o buclă while . Fiecare iterație a buclei funcționează pe o opțiune care a fost transmisă scriptului. În fiecare caz, variabila OPTION este setată la opțiunea identificată de getopts .

Cu fiecare iterație a buclei, getopts trece la următoarea opțiune. Când nu mai există opțiuni, getopts returnează false și bucla while iese.

Cum să utilizați instrucțiunile Case în scripturile Bash
LEGATE Cum să utilizați instrucțiunile de caz în scripturile Bash

Variabila OPTION este comparată cu modelele din fiecare dintre clauzele declarației case. Deoarece folosim o declarație case, nu contează în ce ordine sunt furnizate opțiunile pe linia de comandă. Fiecare opțiune este introdusă în declarația case și este declanșată clauza corespunzătoare.

Clauzele individuale din instrucțiunea case facilitează efectuarea de acțiuni specifice opțiunii în cadrul scriptului. De obicei, într-un script din lumea reală, ați seta o variabilă în fiecare clauză, iar acestea ar acționa ca indicatori mai departe în script, permițând sau interzicând anumite funcționalități.

Copiați acest text într-un editor și salvați-l ca un script numit „options.sh” și faceți-l executabil.

 #!/bin/bash

while getopts 'abc' OPTIUNEA; do
  cazul „$OPTION” în 
    A) 
      echo "Opțiune a folosită" ;;

    b)
      echo „Opțiunea b folosită”
      ;;

    c)
      echo „Opțiunea c folosită”
      ;;

    ?) 
      echo „Utilizare: $(nume de bază $0) [-a] [-b] [-c]”
      iesirea 1
      ;;
  esac
Terminat

Aceasta este linia care definește bucla while.

 while getopts 'abc' OPTIUNEA; do

Comanda getopts este urmată de șirul de opțiuni . Aceasta listează literele pe care le vom folosi ca opțiuni. Doar literele din această listă pot fi folosite ca opțiuni. Deci, în acest caz, -d ar fi invalid. Acest lucru ar fi prins de clauza ?) , deoarece getopts returnează un semn de întrebare „ ? ” pentru o opțiune neidentificată. Dacă se întâmplă acest lucru, utilizarea corectă este tipărită în fereastra terminalului:

 echo „Utilizare: $(nume de bază $0) [-a] [-b] [-c]”

Prin convenție, includerea unei opțiuni între paranteze „ [] ” în acest tip de mesaj de utilizare corectă înseamnă că opțiunea este opțională. Comanda basename elimină toate căile de director din numele fișierului. Numele fișierului script este păstrat în $0 în scripturile Bash.

Să folosim acest script cu diferite combinații de linie de comandă.

 ./opțiuni.sh -a
 ./opțiuni.sh -a -b -c
 ./options.sh -ab -c
 ./opțiuni.sh -cab 

testarea unui script care poate accepta opțiuni de linie de comandă de tip comutator

După cum putem vedea, toate combinațiile noastre de testare de opțiuni sunt analizate și gestionate corect. Ce se întâmplă dacă încercăm o opțiune care nu există?

 ./opțiuni.sh -d 

O opțiune nerecunoscută este raportată de shell și de script

Clauza de utilizare este declanșată, ceea ce este bine, dar primim și un mesaj de eroare din shell. Acest lucru ar putea sau nu conta pentru cazul dvs. de utilizare. Dacă apelați scriptul dintr-un alt script care trebuie să analizeze mesaje de eroare, va fi mai dificil dacă și shell-ul generează mesaje de eroare.

Oprirea mesajelor de eroare shell este foarte ușoară. Tot ce trebuie să facem este să punem două puncte ” : ” ca primul caracter al șirului de opțiuni.

Fie editați fișierul „options.sh” și adăugați două puncte ca prim caracter al șirului de opțiuni, fie salvați acest script ca „options2.sh” și faceți-l executabil.

 #!/bin/bash

while getopts ':abc' OPTIUNEA; do
  cazul „$OPTION” în 
    A) 
      echo „Opțiune a folosită” 
      ;;

    b)
      echo „Opțiunea b folosită”
      ;;

    c)
      echo „Opțiunea c folosită”
      ;;

    ?) 
      echo „Utilizare: $(nume de bază $0) [-a] [-b] [-c]”
      iesirea 1
      ;;
  esac
Terminat

Când rulăm acest lucru și generăm o eroare, primim propriile noastre mesaje de eroare fără mesaje shell.

 ./options2.sh.sh -d 

O opțiune nerecunoscută este raportată numai prin script

Utilizarea getopts cu argumente opțiuni

Pentru a spune getopts că o opțiune va fi urmată de un argument, puneți două puncte ” : ” imediat după litera opțiunii din șirul de opțiuni.

Dacă urmăm „b” și „c” din șirul nostru de opțiuni cu două puncte, getopt se va aștepta la argumente pentru aceste opțiuni. Copiați acest script în editor și salvați-l ca „arguments.sh” și faceți-l executabil.

Amintiți-vă, primele două puncte din șirul de opțiuni sunt folosite pentru a suprima mesajele de eroare shell - nu are nimic de-a face cu procesarea argumentelor.

Când getopt procesează o opțiune cu un argument, argumentul este plasat în variabila OPTARG . Dacă doriți să utilizați această valoare în altă parte a scriptului dvs., va trebui să o copiați într-o altă variabilă.

 #!/bin/bash

while getopts ':ab:c:' OPȚIUNE; do

  cazul „$OPTION” în
    A)
      echo „Opțiune a folosită”
      ;;

    b)
      argB="$OPTARG"
      echo „Opțiunea b folosită cu: $argB”
      ;;

    c)
      argC="$OPTARG"
      echo „Opțiunea c folosită cu: $argC”
      ;;

    ?)
      echo "Utilizare: $(nume de bază $0) [-a] [-b argument] [-c argument]"
      iesirea 1
      ;;
  esac

Terminat

Să rulăm asta și să vedem cum funcționează.

 ./arguments.sh -a -b „cum să faci toci” -c reviewgeek
 ./arguments.sh -c reviewgeek -a 

testarea unui script care poate gestiona argumentele opțiunilor

Deci acum putem gestiona opțiunile cu sau fără argumente, indiferent de ordinea în care sunt date pe linia de comandă.

Dar cum rămâne cu parametrii obișnuiți? Am spus mai devreme că știm că va trebui să le punem pe linia de comandă după orice opțiune. Să vedem ce se întâmplă dacă o facem.

Opțiuni de amestecare și parametri

Vom schimba scriptul nostru anterior pentru a include încă o linie. Când bucla while a ieșit și toate opțiunile au fost gestionate, vom încerca să accesăm parametrii obișnuiți. Vom imprima valoarea în $1 .

Salvați acest script ca „arguments2.sh” și faceți-l executabil.

 #!/bin/bash

while getopts ':ab:c:' OPȚIUNE; do

  cazul „$OPTION” în
    A)
      echo „Opțiune a folosită”
      ;;

    b)
      argB="$OPTARG"
      echo „Opțiunea b folosită cu: $argB”
      ;;

    c)
      argC="$OPTARG"
      echo „Opțiunea c folosită cu: $argC”
      ;;

    ?)
      echo "Utilizare: $(nume de bază $0) [-a] [-b argument] [-c argument]"
      iesirea 1
      ;;
  esac

Terminat

echo „Variabila una este: $1”

Acum vom încerca câteva combinații de opțiuni și parametri.

 ./arguments2.sh dave
 ./arguments2.sh -a dave
 ./arguments2.sh -a -c how-to-geek dave 

Eșecul de a accesa parametrii standard într-un script care acceptă argumente opțiuni

Deci acum putem vedea problema. De îndată ce orice opțiune este utilizată, variabilele $1 în continuare sunt completate cu steagurile opțiunii și argumentele acestora. În ultimul exemplu, $4 ar deține valoarea parametrului „dave”, dar cum o accesați în scriptul dumneavoastră dacă nu știți câte opțiuni și argumente vor fi folosite?

Răspunsul este să utilizați OPTIND și comanda shift .

Comanda shift elimină primul parametru, indiferent de tip, din lista de parametri. Ceilalți parametri „se amestecă în jos”, astfel încât parametrul 2 devine parametrul 1, parametrul 3 devine parametrul 2 și așa mai departe. Și astfel $2 devine $1 , $3 devine $2 și așa mai departe.

Dacă oferiți shift cu un număr, va elimina atât de mulți parametri din listă.

OPTIND numără opțiunile și argumentele pe măsură ce sunt găsite și procesate. Odată ce toate opțiunile și argumentele au fost procesate, OPTIND va fi cu unul mai mare decât numărul de opțiuni. Deci, dacă folosim shift pentru a tăia (OPTIND-1) parametrii din lista de parametri, vom rămâne cu parametrii obișnuiți din $1 în continuare.

Exact asta face acest script. Salvați acest script ca „arguments3.sh” și faceți-l executabil.

 #!/bin/bash

while getopts ':ab:c:' OPȚIUNE; do
  cazul „$OPTION” în
    A)
      echo „Opțiune a folosită”
      ;;

    b)
      argB="$OPTARG"
      echo „Opțiunea b folosită cu: $argB”
      ;;

    c)
      argC="$OPTARG"
      echo „Opțiunea c folosită cu: $argC”
      ;;

    ?)
      echo "Utilizare: $(nume de bază $0) [-a] [-b argument] [-c argument]"
      iesirea 1
      ;;
  esac
Terminat

echo „Înainte - variabila una este: $1”
shift „$(($OPTIND -1))”
echo „După - variabila unu este: $1”
echo „Restul argumentelor (operanzilor)”

pentru x în „$@”
do
  eco $x
Terminat

Vom rula acest lucru cu un amestec de opțiuni, argumente și parametri.

 ./arguments3.sh -a -c „Dave Dee” mick tich 

Accesarea corectă a parametrilor standard într-un script care acceptă argumente opțiuni

Putem vedea că înainte de a numi shift , $1 ținea „-a”, dar după comanda shift $1 deține primul nostru parametru non-opțiune, non-argument. Putem parcurge toți parametrii la fel de ușor ca într-un script fără opțiune de analizare.

Întotdeauna este bine să ai opțiuni

Gestionarea opțiunilor și a argumentelor acestora în scripturi nu trebuie să fie complicată. Cu getopts puteți crea scripturi care gestionează opțiunile, argumentele și parametrii din linia de comandă exact așa cum ar trebui scripturile native compatibile cu POSIX.