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

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.


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.


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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.