2012-02-24 18 views
10

Mam skrypt, który wyświetla za każdym razem około 10 wierszy. Zawartość tych linii jest różna.Możliwe potokowanie w instrukcji if?

Naprawdę chciałbym być w stanie grep na wyjściu i robić różne rzeczy w zależności od wyjścia.

W pseudo to jest to, co chciałbym zrobić

cat /etc/password | \\ 
if [ grep "root" $STDOUT ]; then 
    echo "root is found" 

elif [ grep "nobody" $STDOUT ]; then 
    echo "nobody is found" 

fi 

Tutaj mają użyłem cat /etc/password jako przykład, ale powinien on być zastąpiony moich skryptów wymienionych powyżej.

Problem polega na tym, w jaki sposób uzyskać dane wyjściowe z cat /etc/password w warunkach if/elif?

+1

Może awk lub perl są lepiej dostosowane do zadania .. – bew

+2

nie używaj 'cat', jeśli intencja nie jest wyświetlana ani konkatenowana. Tutaj możesz po prostu podać plik w wierszu poleceń grep, ponieważ jest on akceptowany, w przeciwnym razie możesz po prostu przekierować plik ('<'). – Benoit

+2

Nie potrzebujesz kontynuacji linii po '|', '&&' i '||' –

Odpowiedz

5

Jak zaleca @Benoit, po prostu użyj grep bezpośrednio.

Jak zauważa @larsmans, można uniknąć podwójnego odczytu pliku, odczytując go raz jako zmienną.

Biorąc pod uwagę dostępność bash zrobiłbym to tak:

password=$(< /etc/passwd) 

if grep -q root <<< "$password" ; then 
    echo root found 
elif grep -q nobody <<< "$password" ; then 
    echo nobody found 
fi 

odczytać pliku, jeden lub dwa wezwania z grep, żadne inne procesy lub podpowłok uruchomione.

+0

Bardzo interesujące rozwiązanie. Dlaczego w pierwszym wierszu masz 'IFS ='? –

+2

W bashu możesz po prostu powiedzieć 'password = $ (

+0

Dobry punkt widzenia, zapomniałem o tym. – Sorpigal

3

po prostu zrobić:

if grep -q "root" /etc/passwd ; then 
    ... 
fi 

który zagra polecenia ... jeśli kod wyjścia grep 0.

pamiętać, że \[ is a external command, prawdopodobnie znajduje się w /usr/bin/[ (zwykle jest to trudne link test i kiedy wywoływany jako [ wymaga zgodnego argumentu ]). Zobacz także stronę pitfalls tutaj, wiele z nich dotyczy związanych z tym poleceniem.

+1

+1, ale możesz chcieć dodać '-q' do' grep', aby pominąć wyjście. – Sorpigal

1

Doprowadzenie do instrukcji if jest możliwe z podpowłokami, ale to rozwiązanie zostanie przerwane, ponieważ użytkownik wykonuje dwa polecenia na rurze, z których pierwszy będzie go wyczerpywał.

Najlepszym rozwiązaniem w Twoim przypadku to chyba czytać /etc/passwd do zmiennej, a następnie grep go:

passwd=$(cat /etc/passwd) 
if (echo $passwd | grep -q root); then 
    echo "root found" 
fi 
if (echo $passwd | grep -q nobody); then 
    echo "nobody found" 
fi 
+0

Tańsze jest powiedzenie "IFS = read -r -d" "password Sorpigal

+0

OK, ale nie rozumiem, jak to gwarantuje wartość -1. –

+2

Nie ma. Nie wiem, kto to zrobił, ale przeciwstawiłem się głosowaniu w oburzeniu. – Sorpigal

3

Sugeruję użyciu awk:

cat /etc/passwd | awk '/root/{ do something }/nobody/{ do something else }' 

można osiągnąć to samo w bash przy użyciu wyrażenia takiego jak:

cat /etc/passwd | 
while read; do 
    if echo "$REPLY" | fgrep root; then 
    something 
    fi 
    if echo "$REPLY" | fgrep nobody; then 
    something_else 
    fi 
done 

Jednak czysty ba Rozwiązanie sh jest mniej wydajne dla dużych wejść, ponieważ uruchamia oddzielne instancje grep dla każdej linii.

+0

Nie używaj 'cat' w ten sposób, możesz przekazać' passwd' bezpośrednio do 'awk',' while', etc .. – Sorpigal

+1

Prawda, ale często jest bardziej czytelna w ten sposób, ponieważ źródło danych jest na pierwszym planie, a dla parsowania kilkudziesięciu linii wydajność nie jest problemem. W tej skali jest to tylko kwestia osobistych preferencji, a nie powodu do głosowania. –

0

W ogólnym przypadku można użyć pliku tymczasowego.

t=$(mktemp -t passwd.XXXXXXXX) 
trap 'rm $t' 0 
trap 'exit 127' 1 2 3 5 15 
cat >$t 
for u in root nobody; do 
    fgrep $u $t 
done 

Po usunięciu pliku tymczasowego pliki trap.

Tak na marginesie, to może rura do if, ale pierwszy grep wewnątrz warunkowy będzie już spożywać wszystkie jego standardowego wejścia. To jest bardziej przydatny w takich sytuacjach:

if $option_count ; then 
    wc -l 
else 
    tac 
fi <file 
1

Wystarczy użyć & &:

grep -q root /etc/password && echo "root is found" 

grep -q nobody /etc/password && echo "nobody is found" 
0

Jak o następujące elementy:

#!/bin/bash 

if [ -z $1 ]; then 
    echo Usage: $0 [UID to search for] 
    exit 1; 
fi 

SEARCHID="$1" 

function notFound() { 
    echo NOT FOUND 
} 

function found() { 
    echo Found it 
} 

function main() { 

    grep -i $SEARCHID /etc/passwd 
    # Move $? to a variable 
    SEARCHRESULT=$? 

    if [ "$SEARCHRESULT" != "0" ]; then 
     notFound; 
    else 
     found; 
    fi 
} 

# call main function 
main 
Powiązane problemy