Newsgroup: it.comp.os.linux.iniziare
Titolo: get parametri e performance

in bash, per prelevare i parametri dati in command line io ho fatto
        while [ ! -z "$*" ];do
               case $1 in
                       "-p" ) shift; P="$1"; shift;;
                       "-f" ) shift; F="$1"; shift;;
                       "-s" ) shift; S=$1; shift;;
                       *) X="$X $1"; shift;;
               esac
        done
in cui la commandline è
comando [ -p <argP> ] [ -f <argF> ] [ -s argS ] <argX> <argX> ...
solo che, da qualche test, questo ciclo mi risulta un bel collo di
bottiglia sulle prestazioni del mio script (che è di due/tre righe più
quelle di cui sopra), che risulta visibilmente più rapido togliendo
quel blocco. Considerando anche che questo script viene lanciato anche
in blocchi di un centinaio.
Esiste un sistema un po' più performante?
Matteo

 ...
for par in
 do
  case $par in
   .....
   --|*) break ;;
  esac
  .....
done  

 done
mmm.
for par in <che cosa> ?
io devo trasformare questo
comando [ -p <argP> ] [ -f <argF> ] [ -s argS ] <argX> <argX> ...
in
P=<argP>
F=<argF>
S=<argS>
X="<argX> <argX> ... "
dò per presupposto che l'utente non sbagli sintassi
Matteo

 Matteo
HTH,
David
P.S.: conoscete un modo di fare quel for in bash-style e non in c-style?
:-P (probabilmente un while?)
-- 
         Linux Registered User #334216
Get FireFox! >> 
http://snipurl.com/gofoxygo/
 <<
Blog         >>  
http://www.hanskalabs.net/
  <<
Staff        >> 
http://www.debianizzati.org/
 <<

 dò per presupposto che l'utente non sbagli sintassi
Io metterei un minimo di controllo sull'
argomento delle opzioni.
Tornando a noi se incontri una opzione devi 
ricordarti che il prossimo parametro e` l'
argomento della opzione e poi porti il conto 
dei parametri processati; quando finisci le
opzioni dai un "break" e uno "shift nparametri"

 opzioni dai un "break" e uno "shift nparametri"
niente; ho fatto prove su prove ma questa sintassi non riesco ad
implementarla.
Matteo

 riesco ad implementarla.
ne parliamo dopo pranzo

Cosa ne pensate di questa?
$(echo $*|sed -e 's/^\(.*\)/export \1 /' \
                -e 's/-\(.\) *\([^ ]*\)/\1=\2/g' \
                -e 's/\(export \(.=[^ ]* \+\)*\) *\(.*\)/\1arg=\3/'
)
traduzione:
prende la stringa della cmdline, p.e.:
-p argP -f argF -s argS argomento
con sed, il primo -e ci aggiunge un 'export' davanti ed uno spazio
alla fine, e siamo a
'export -p argP -f argF -s argS argomento '
con il secondo -e aggiungo un = tra ogni parametro e argomento del
parametro, togliendo il -, e siamo a
'export p=argP f=argF s=argS argomento '
il terzo -e aggiunge un arg= prima di 'argomento', e siamo a
'export p=argP f=argF s=argS arg=argomento'
poi la eseguo
$(export p=argP  f=argF  s=argS  arg=argomento )
risultato
p=argP
f=argF
s=argS
arg=argomento
certo, la sintassi dei parametri deve essere rigorosamente perfetta,
ma funziona. arg= viene aggiunto anche se 'argomento' non è
specificato
un po' elaborata, ma è solo un esperimento (tanto per vedere quanto
conosco le regexp)
Matteo


errata corrige:
$(echo $A|sed -e 's/^\(.*\)/export \1 /'
                         -e 's/ -\(.\) *\([^ ]*\)/ \1=\2/g'
                         -e 's/\(export \(.=[^ ]* \+\)*\) *\(.*\)/
\1arg=\3/'
)
corregge un bug secondo cui l'argomento non poteva contenere trattini
Matteo

 riesco ad implementarla.
flag=''
ns=0
np=0
nf=0
n=0
for i
 do
  case $i in
   -s) if [[ $ns -eq 0 ]]
         then 
           (( n++  ))
           (( ns++ ))
           flag=s
         else 
          echo "-s duplicato"
          exit 1
       fi ;;
   -p) if [[ $np -eq 0 ]]
         then
           (( n++ ))
           (( np++ ))
           flag=p
         else 
          echo "-p duplicato."
          exit 2
       fi ;;
   -f) if [[ $nf -eq 0 ]]
         then
           (( n++ )) 
           (( nf++ ))
           flag=f
         else 
          echo "-f duplicato."
          exit 3
       fi ;;
    *) (( n++ ))
       case $flag in
         s) echo "$i e\` l\'argomento di -s"
            flag=''
            ;;
         p) echo "$i e\` l\'argomento di -p"
            flag=''
            ;;
         f) echo "$i e\` l\'argomento di -f"
            flag=''
            ;;
         *) (( n-- ))
            shift $n
            break 
           ;;
      esac ;;
    esac  
  done
shift $n  
echo -n "Gli argomenti sono: "
echo $@
*ATTENTO*
ci sono parecchie cose che non vanno
 
 
 
 
 

 )
Meglio sarebbe
case $1 in
 -p)  argp=$2
      ...
      ;;
 -s) args=$2
     ...
     ;;
 -f) argf=$2
     ...
     ;;
  *) ... ;;
esac
case $3 in
 -p)  argp=$4
      ...
      ;;
 -s) args=$4
     ...
     ;;
 -f) argf=$4
     ...
     ;;
  *) ... ;;
esac
et cetera
 


ne passa un po' eh.
Grazie,
Matteo

 ...
Non credo.
Certio che in C ci sono delle funzioni di 
libreria che effettuano il parsing dei 
parametri ed e ` tutto molto piu` facile.
La cosa che mi pareva strana e` che la bash 
ne mancasse, cosi` ho indagato ed ho scoperto 
una cosa nuova (per me):
man -a getopt{,s}
Le sto studiando.


no, non funzionerebbe.
Questa prevederebbe che io i parametri li inserisca tutti, mentre nel
mio caso sono tutti facoltativi; inoltre se in futuro voglio
aggiungere un parametro lo devo mettere in tutte le case e devo
aggiungere una case.
La mia regexp era giusto una finezza, per dimostrarne la fattibilità.
Per come è strutturata porta un vantaggio su TUTTE le soluzioni finora
proposte e quelle proponibili con l'uso di case:
è flessibile, nel senso che non è necessario sapere a priori quali
siano i parametri che deve avere la command line. Inoltre ha le
performance massime perchè non deve elaborare strutture di controllo,
cicli e quant'altro.
porta ovviamente anche degli svantaggi non piccoli:
tutti i valori delle opzioni e argomenti non possono contenere spazi
(non va bene la soluzione "stringa con spazi" né stringa\ con\ spazi)
è possibile specificare un solo argomento
le opzioni non possono essere switch secchi, ma devono tutti avere un
valore (non è accettata la sintassi '-a -b argB argomento'); il valore
di un parametro può essere una stringa nulla ma va specificato con ""
le opzioni devono essere composte di un solo carattere
non c'è assolutamente nessun controllo di errori (se vengono
specificati due argomenti da errore; se viene duplicata una opzione
prende solo l'ultima)
non è certo la soluzione migliore per uno script da dare all'utente, e
gli attakker ci sguazzerebbero dentro; tuttavia è la soluzione
migliore per chi vuole performance (anche se chi vuole vere
performance lo script se lo scrive in C)
Matteo

 La mia regexp era giusto una finezza,...
No, era un obbrobrio.
*IL* modo elegante per fare il parsing e` ricorrere 
a getopts, ma credevo che la bash ne mancasse.


Non mi ero proprio posto la domanda se potesse esistere un metodo
built-in; la man page di bash l'ho letta diverse volte per 100
problemi diversi (però ho letto solamente la parte di manpage alla
ricerca del problema del momento).
Ora credo che mi fermerò dal cercare la soluzione migliore per il
parsing della cmdline perchè mi risulta più urgente il problema di
performance del resto dell'algoritmo (sono sicuro che posso portarlo
da O(N^2) a O(N), anche se mi comporterà complicarlo un pochino)
La soluzione in C (teorica, nel senso che non farò il mio programma in
C) la penso più rapida non perchè esistono librerie prefatte, ma bensì
perchè è un linguaggio di tipo compilato.
Matteo
P.S.: ricordavo di aver scritto questo post ieri, ma non lo vedo