grep en una variable

58

Digamos que tengo una variable

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

ahora quiero grep cuántas veces se produce select en la oración.

grep -ci "select" $line

Lo intenté, pero no funcionó. También intenté

grep -ci "select" "$line"

Aún no funciona. Obtuve el siguiente error.

grep: This is where we select from a table.: No such file or directory
gkmohit
fuente
1
Necesitas usar hererestring ...<<<"$line" . El comando grepestá esperando un archivo en su lugar
Valentin Bajrami
stackoverflow.com/questions/2106526/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Respuestas:

85

He grepleído en su entrada estándar. Ahí tienes, usando una pipa ...

$ echo "$line" | grep select

... o una cadena aquí ...

$ grep select <<< "$line"

Además, es posible que desee reemplazar espacios por nuevas líneas antes de grepping:

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

... o puede pedir grepimprimir solo la coincidencia:

$ echo "$line" | grep -o select

Esto te permitirá deshacerte del resto de la línea cuando haya una coincidencia.

Editar: Vaya, lee un poco demasiado rápido, gracias Marco . Para contar las ocurrencias, simplemente conecte cualquiera de estos a wc(1);)

Otra edición realizada después del comentario de lzkata , citando $lineal usar echo.

John WH Smith
fuente
3
Dado que el OP quiere contar el número de ocurrencias de una cadena, puede agregar un wcpara completar la tarea:grep -o <string> <<< "$variable" | wc -l
Marco
2
Úselo echo "$line"para preservar las nuevas líneas existentes en lugar de tr
crearlas
¿Cuál es la disponibilidad de una cadena aquí? ¿Requiere Bash u otro shell?
Según Wikipedia , aquí las cadenas están disponibles en bash, ksh y zsh (pero supongo que puede haber otras).
John WH Smith
7
test=$line i=0
while case "$test" in (*select*)
test=${test#*select};;(*) ! :;;
esac; do i=$(($i+1)); done

No necesita llamar grepa algo tan simple.

O como una función:

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

Se necesitan 2 o 3 args. Proporcionar más que eso sesgará sus resultados. Puedes usarlo como:

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

... que imprime el recuento de ocurrencias de .in ...si ocurre al menos 2 veces. Me gusta esto:

count: 3

Si $_occurestá vacío o unsetcuando se invoca, no afectará a ninguna variable de shell y return1 si "$2"ocurre en "$1"menos de una "$3"vez. O, si se llama con solo dos args, será return1 solo si "$2"no está en "$1". De lo contrario, devuelve 0.

Y así, en su forma más simple, puedes hacer:

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

... que imprime ...

shite

...pero...

occur . . && echo yay || echo shite

... imprimirá ...

yay

También puede escribirlo de manera un poco diferente y omitir las comillas $2en la declaración (*"$2"*)y "${1#*"$2"}". Si haces eso, puedes usar globos de concha para partidos como sh[io]tepara la prueba de partidos.

mikeserv
fuente
1
+1: Más rápido, de hecho. Funciona en bashy dash/ sh(y probablemente en algunos otros).
John WH Smith
@JohnWHSmith: la edición es mejor, pero igual de portátil.
mikeserv