grep na zmiennej


58

Powiedzmy, że mam zmienną

line="This is where we select from a table."

teraz chcę grep, ile razy zaznaczenie występuje w zdaniu.

grep -ci "select" $line

Próbowałem tego, ale to nie zadziałało. Też próbowałem

grep -ci "select" "$line"

To wciąż nie działa. Pojawia się następujący błąd.

grep: This is where we select from a table.: No such file or directory

1
Musisz użyć herestring ...<<<"$line" . grepZamiast tego polecenie oczekuje pliku
Valentin Bajrami

Odpowiedzi:


85

Czy grepprzeczytać na jego standardowego wejścia. Proszę bardzo, używając rury ...

$ echo "$line" | grep select

... lub ciąg tutaj ...

$ grep select <<< "$line"

Przed grepowaniem możesz też zastąpić spacje znakiem nowej linii:

$ echo "$line" | tr ' ' '\n' | grep select

... lub możesz poprosić grepo wydrukowanie tylko meczu:

$ echo "$line" | grep -o select

Pozwoli ci to pozbyć się reszty linii, gdy pojawi się dopasowanie.

Edycja: Ups, czytaj trochę za szybko, dzięki Marco . Aby policzyć zdarzenia, po prostu potokuj dowolne z nich wc(1);)

Kolejna edycja wykonana po komentarzu lzkaty , cytująca $lineprzy użyciu echo.


3
Ponieważ OP chce policzyć liczbę wystąpień ciągu, możesz dodać a, wcaby wykonać zadanie:grep -o <string> <<< "$variable" | wc -l
Marco

2
Użyj, echo "$line"aby zachować istniejące nowe wiersze zamiast tworzyć je za pomocątr
Izkata,

Jaka jest dostępność ciągu tutaj? Czy wymaga Bash lub innej powłoki?

Według Wikipedii ciągi tutaj są dostępne w bash, ksh i zsh (ale zakładam, że mogą istnieć inne).
John WH Smith

7
test=$line i=0
while case "$test" in (*select*)
test=${test#*select};;(*) ! :;;
esac; do i=$(($i+1)); done

Nie musisz dzwonić greppo tak prostą rzecz.

Lub jako funkcja:

occur() while case "$1" in (*"$2"*) set -- \
        "${1#*"$2"}" "$2" "${3:-0}" "$((${4:-0}+1))";;
        (*) return "$((${4:-0}<${3:-1}))";;esac
        do : "${_occur:+$((_occur=$4))}";done

Zajmuje 2 lub 3 argumenty. Podanie czegoś więcej wykrzywi jego wyniki. Możesz go używać w następujący sposób:

_occur=0; occur ... . 2 && echo "count: $_occur"

... który wypisuje liczbę wystąpień .w, ...jeśli występuje co najmniej 2 razy. Lubię to:

count: 3

Jeśli $_occurjest pusty lub unsetgdy zostanie wywołany, nie wpłynie w ogóle na żadne zmienne powłoki, a return1, jeśli "$2"wystąpi "$1"krócej niż "$3"razy. Lub, jeśli zostanie wywołany tylko z dwoma argumentami, wyniesie return1 tylko wtedy, gdy "$2"nie ma go "$1". W przeciwnym razie zwraca 0.

I tak w najprostszej formie możesz:

occur '' . && echo yay || echo shite

... które drukuje ...

shite

...ale...

occur . . && echo yay || echo shite

... wydrukuje ...

yay

Możesz także napisać to nieco inaczej i pominąć cudzysłowy $2zarówno w instrukcji, jak (*"$2"*)i "${1#*"$2"}". Jeśli to zrobisz, możesz użyć globów powłoki do dopasowań, takich jak sh[io]tetest dopasowania.


1
+1: Rzeczywiście, szybciej. Działa w bashi dash/ sh(i prawdopodobnie kilka innych).
John WH Smith

@JohnWHSmith - edycja jest lepsza, ale nadal równie przenośna.
mikeserv
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.