grep em uma variável

58

Digamos que eu tenho uma variável

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

agora eu quero grep quantas vezes o select ocorre na frase.

grep -ci "select" $line

Eu tentei isso, mas não funcionou. Eu também tentei

grep -ci "select" "$line"

Ainda não funciona. Estou tendo o erro a seguir.

grep: This is where we select from a table.: No such file or directory
gkmohit
fonte
11
Você precisa usar herestring ...<<<"$line" . O comando grepestá esperando um arquivo em vez disso
Valentin Bajrami 23/10

Respostas:

85

Ter greplido em sua entrada padrão. Lá vai você, usando um cachimbo ...

$ echo "$line" | grep select

... ou uma string aqui ...

$ grep select <<< "$line"

Além disso, convém substituir espaços por novas linhas antes de grepping:

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

... ou você pode pedir apenas greppara imprimir a correspondência:

$ echo "$line" | grep -o select

Isso permitirá que você se livre do resto da linha quando houver uma correspondência.

Edit: Opa, leia um pouco rápido demais, obrigado Marco . Para contar as ocorrências, basta canalizar uma delas para wc(1);)

Outra edição feita após o comentário de lzkata , citando $lineao usar echo.

John WH Smith
fonte
3
Como o OP deseja contar o número de ocorrências de uma sequência, você pode adicionar a wcpara concluir a tarefa:grep -o <string> <<< "$variable" | wc -l
Marco
2
Use echo "$line"a preservar novas linhas existentes em vez de criar queridos comtr
Izkata
Qual é a disponibilidade de uma String Here? Requer Bash ou outro shell?
De acordo com a Wikipedia , aqui as strings estão disponíveis no bash, ksh e zsh (mas suponho que possam existir outras).
John WH Smith
7
test=$line i=0
while case "$test" in (*select*)
test=${test#*select};;(*) ! :;;
esac; do i=$(($i+1)); done

Você não precisa pedir grepuma coisa tão simples.

Ou como uma função:

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

Leva 2 ou 3 args. Fornecer mais do que isso distorcerá seus resultados. Você pode usá-lo como:

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

... que imprime a contagem de ocorrências de .in ...se ocorrer pelo menos 2 vezes. Como isso:

count: 3

Se $_occurestiver vazio ou unsetquando for chamado, não afetará nenhuma variável de shell e return1 se "$2"ocorrer em "$1"menos de "$3"vezes. Ou, se chamado com apenas dois argumentos, será return1 apenas se "$2"não estiver dentro "$1". Caso contrário, ele retorna 0.

E assim, na sua forma mais simples, você pode fazer:

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

... que imprime ...

shite

...mas...

occur . . && echo yay || echo shite

... imprimirá ...

yay

Você também pode escrever um pouco diferente e omitir as aspas $2na declaração (*"$2"*)e "${1#*"$2"}". Se você fizer isso, poderá usar shell globs para correspondências como sh[io]tepara o teste de correspondência.

mikeserv
fonte
11
+1: Mais rápido, de fato. Trabalha em bashe dash/ sh(e provavelmente alguns outros).
John WH Smith
@ JohnWHSmith - a edição é melhor, mas ainda assim tão portátil.
mikeserv