De acordo com o título da pergunta, o problema é que você tem uma matriz contendo uma lista de strings que você deseja buscar, mas o grep requer uma única expressão regular ou várias opções -e
.
(você pode usar -f
e fornecer as strings de um arquivo ou pipe ou processo de substituição, mas minha resposta é focada em usar uma matriz. ou apenas uma lista de strings).
A abordagem simples, de fazer loop em cada elemento da matriz e gerar o |
como um prefixo ou sufixo para cada elemento, acaba com uma string que possui um |
inicial ou final a ser removido. Facilmente feito, mas irritante ... e você não deveria ter que, deve haver uma função interna que une strings arbitrárias com um separador arbitrário.
perl
tem uma função join()
muito útil que pode ser usada para esse tipo de coisa. Infelizmente, bash
não ... mas é fácil criar um.
function join() {
# input:
# $1 - separator string
# $2...$n - list of items to join
#
# output:
# a joined string on stdout.
local sep result i
sep="$1" ; shift
result="$1" ; shift
for i in "$@" ; do result="$result$sep$i" ; done
printf '%s' "$result"
}
Observação: essa join
function deliberadamente não anexa uma nova linha ao final da string de saída. Você pode adicionar facilmente um, se precisar (por exemplo, com echo
, como nos exemplos abaixo). Também seria fácil adicionar uma opção para alterar a string printf
format para %s\n
... como uma primeira opção opcional antes do argumento do separador ou, para fazer isso corretamente, usando getopts
.
Observe também: o nome da função join
está em conflito com o utilitário padrão join
(que associa linhas correspondentes de dois arquivos). Eu nunca uso /usr/bin/join
(porque nunca coincide exatamente com o que eu preciso fazer, então eu acabo tendo que escrever um script perl ou awk), então eu não me importo. Eu sempre posso substituir a função com command join file1 file2
ou similar de qualquer maneira, se eu precisar. Se você se importa, renomeie para joinarray
ou joinstrings
ou algo assim. Eu prefiro join
para que seja o mesmo nome da função perl
.
De qualquer forma, com essa função em seu ambiente de shell ou em seu script, você pode fazer coisas como:
$ join '|' a b c d e
a|b|c|d|e$ _
(isso é feio, não há nova linha, então o próximo prompt $
aparece na mesma linha que a saída. use echo
enquanto testa esta função na linha de comando)
$ echo $(join '|' a b c d e)
a|b|c|d|e
$ echo $(join '|' a b c 'd e')
a|b|c|d e
$ echo '^('$(join '|' a b c 'd e' 'f g h')')$'
^(a|b|c|d e|f g h)$
Lembre-se de citar e / ou escapar de qualquer texto que precise.
Esta função é útil para mais do que apenas os operadores regexp |
alternation ( OR
).
$ csv=$(join ',' foo bar baz)
$ echo "$csv"
foo,bar,baz
$ echo $(join ':' user pass uid gid gecos home shell)
user:pass:uid:gid:gecos:home:shell
ou juntando uma matriz:
date_array=( $(cat dates.txt) )
date_ere='('$(join '|' "${date_array[@]}")')' # extended regexp
date_re='\('$(join '\|' "${date_array[@]}")'\)' # basic regexp
grep "$date_re" filesystem.txt
ou até mesmo:
grep -E "($(join '|' $(cat dates.txt)))" filesystem.txt
awk
também não tem uma função join
. aqui está a mesma função implementada para o awk. As funções bash
e awk
são modeladas no separador perl
function - como primeiro argumento, matriz / lista como argumentos subseqüentes.
function join(sep,array, i) {
result=array[1];
for (i=2;i<=length(array);i++) result = result sep array[i];
return result;
};