Come posso usare il valore di una pipe nel programma di test?


10
wc -l | test -eq 1

Questo non funziona Voglio confrontare il risultato di wc con il valore di 1. Come posso farlo?

Risposte:


9

Non risponde alla tua domanda sui tubi, ma puoi riorganizzare:

test $(ls -l | wc -l) -eq 1 && echo "worked"

E ci sono alcune soluzioni su SO , questo è il più bello:

ls -l | wc -l | { read wc; test $wc -eq 7 && echo "woohoo"; }

4

Se stai usando Bash, probabilmente vorrai ricercare la variabile PIPESTATUS. Come notato nella guida di riferimento di Bash , PIPESTATUS lo è

Una variabile di matrice (vedere Array) contenente un elenco di valori dello stato di uscita dai processi nella pipeline di primo piano eseguita più di recente (che può contenere solo un singolo comando).

Con PIPESTATUS possiamo scoprire quali erano i codici di uscita per questa pipeline:

dmesg | grep -iw 'nnse' | wc -l

Se ora si esegue una query sulla variabile array, si ottengono gli stati di uscita facendo riferimento ai comandi utilizzati nella pipeline:

echo ${PIPESTATUS[@]}
0 1 0

(In una matrice indicizzata, quei codici di uscita sopra sono rappresentati da 0 1 e 2 nella matrice poiché le matrici iniziano sempre da 0 in Bash.)

Qui vediamo il secondo comando restituito 1 e il resto 0; tuttavia, wc -lrestituisce 0 se sono presenti zero corrispondenze, il che non è un errore. Il fallimento è rappresentato con un valore diverso da zero e ci sono altri valori di errore come 127 che non è stato trovato il comando, e ancora più codici che possono essere specifici del programma in questione.

Se vuoi vedere quale fosse il codice di uscita di un particolare comando nella pipeline, puoi semplicemente accedere a quel valore. Il comando grep era il secondo comando nella pipeline sopra, ma poiché gli array iniziano da 0, abbiamo bisogno di immetterne uno.

Quindi, per scoprire il codice di uscita del comando grep, eseguire nuovamente la pipeline sopra (poiché il contenuto di PIPESTATUS sarà esaurito se è stato eseguito echo ${PIPESTATUS[@]}) e quindi eseguire il comando seguente, che restituirà 1 (il codice di uscita):

echo ${PIPESTATUS[1]}
1

In uno script, assicurarsi che la pipeline abbia terminato l'esecuzione prima di cercare il contenuto della variabile di array PIPESTATUS.

Per un esempio di uso interessante della variabile di array PIPESTATUS, vedere questa risposta relativa alla combinazione del raggruppamento dei comandi Bash e dello stato della pipe . Potresti testare la variabile array nel modo suggerito da Gilles nei commenti, anche se dovrai prima eseguire nuovamente la pipeline:

dmesg | grep -iw 'nnse' | wc -l
[ ${PIPESTATUS[1]} -eq 1 ] && do_something_here

Questo è solo un frammento, poiché non so che tipo di sceneggiatura intendi, ma spero che conoscere PIPESTATUS possa esserti utile. Esistono molte variabili di array Bash come PIPESTATUS che possono essere estremamente utili; consultare la guida di riferimento di Bash per l'intero elenco e gli altri siti Stackexchange per esempi sul loro utilizzo.


2

Il modo più semplice è probabilmente usare xargs :

wc -l | xargs -I % test % -eq 1

1

Questo non copre tutti i testcasi, ma se è possibile utilizzare un'espressione regolare e grepla stringa con pipe, è piuttosto semplice perché grepè test-come in quanto ha un'uscita diversa da zero quando non viene trovata alcuna corrispondenza

cat file | wc -l | grep -qE '^\s*1\s*$'

Le espressioni regolari estese consentono di coprire molti casi con questa tecnica. Per risatine, un caso di prova:

for i in 1 11 '' foo; do 
  if echo $i | grep -qE '^\s*1\s*$'; then 
    echo "'$i' matched"
  else
    echo "'$i' didn't match."
  fi
done

uscite:

'1' matched
'11' didn't match.
'' didn't match.
'foo' didn't match.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.