Grep auf eine Variable

58

Nehmen wir an, ich habe eine Variable

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

jetzt möchte ich mal gucken wie oft select im satz vorkommt.

grep -ci "select" $line

Ich habe es versucht, aber es hat nicht funktioniert. Ich habe es auch versucht

grep -ci "select" "$line"

Es funktioniert immer noch nicht. Ich erhalte den folgenden Fehler.

grep: This is where we select from a table.: No such file or directory
gkmohit
quelle
1
Sie müssen Herestring verwenden ...<<<"$line" . Der Befehl greperwartet stattdessen eine Datei
Valentin Bajrami

Antworten:

85

Habe grepauf seiner Standardeingabe gelesen. Los geht's mit einer Pfeife ...

$ echo "$line" | grep select

... oder eine hier Zeichenfolge ...

$ grep select <<< "$line"

Sie können auch Leerzeichen durch Zeilenumbrüche ersetzen, bevor Sie mit dem Greifen beginnen:

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

... oder Sie könnten nur darum bitten grep, das Match auszudrucken:

$ echo "$line" | grep -o select

Auf diese Weise können Sie den Rest der Leitung loswerden, wenn eine Übereinstimmung vorliegt.

Edit: Ups, lies ein bisschen zu schnell, danke Marco . Um die Vorkommen zu zählen, leiten Sie einfach eines davon an wc(1);)

Eine weitere Änderung , die nach dem Kommentar von lzkata vorgenommen wurde und $linebei der Verwendung zitiert wird echo.

John WH Smith
quelle
3
Da das OP die Anzahl der Vorkommen eines Strings zählen möchte, können Sie ein hinzufügen wc, um die Aufgabe abzuschließen:grep -o <string> <<< "$variable" | wc -l
Marco
2
Verwenden Sie echo "$line"diese Option, um vorhandene Zeilenumbrüche beizubehalten, anstatt sie mittr
Izkata 23.10.14
Was ist die Verfügbarkeit eines Here-Strings? Benötigt es Bash oder eine andere Shell?
Laut Wikipedia sind hier Zeichenfolgen in bash, ksh und zsh verfügbar (aber ich gehe davon aus, dass es andere geben kann).
John WH Smith
7
test=$line i=0
while case "$test" in (*select*)
test=${test#*select};;(*) ! :;;
esac; do i=$(($i+1)); done

Sie müssen nicht nach grepso einer einfachen Sache rufen .

Oder als Funktion:

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

Es dauert 2 oder 3 Argumente. Wenn Sie mehr als das bereitstellen, werden die Ergebnisse verzerrt. Sie können es wie folgt verwenden:

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

... der die Häufigkeit von .in ...ausgibt, wenn sie mindestens zweimal auftritt. So was:

count: 3

Wenn $_occurleer ist oder unsetwenn es aufgerufen wird, wirkt es sich überhaupt nicht auf Shell-Variablen aus und return1, wenn "$2"es "$1"weniger als "$3"einmal auftritt . Oder, wenn mit nur zwei Argumenten aufgerufen, wird return1 nur, wenn "$2"nicht in ist "$1". Anderenfalls wird 0 zurückgegeben.

In seiner einfachsten Form können Sie also Folgendes tun:

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

... was druckt ...

shite

...aber...

occur . . && echo yay || echo shite

... wird gedruckt ...

yay

Man könnte es auch ein wenig anders schreiben und die Anführungszeichen weglassen um $2in der beide (*"$2"*)und "${1#*"$2"}"Aussage. Wenn Sie das tun, können Sie Shell-Globs für Matches wie sh[io]tefür den Match-Test verwenden.

mikeserv
quelle
1
+1: In der Tat schneller. Funktioniert in bashund dash/ sh(und wahrscheinlich auch in einigen anderen).
John WH Smith
@JohnWHSmith - der Schnitt ist besser, aber trotzdem genauso portabel.
mikeserv