grep para múltiplos argumentos, mas imprimi-los por ordem de aparecimento

1

Eu quero tirar o material de um arquivo de saída. Por exemplo, ab e cd .

O arquivo parece:

asdf
ab
hgr
cd
ab
asdsda

se agora eu grudo por ab e cd um após o outro como

for i in $@
do
  grep $i file
done

Eu obtenho

ab
ab
cd

O que eu quero é

ab
cd
ab

Existe uma solução elegante?

    
por Fl.pf. 27.10.2017 / 09:45

2 respostas

3

Você obtém esse resultado porque o loop primeiro executa grep ab file e retorna todas as ocorrências de ab na primeira iteração e após esse loop executa grep cd file e retorna todas as ocorrências cd em file .

Você não precisa de um loop for . Tente isto :

grep -e "^ab$" -e "^cd$" file

Ou use a opção -x para selecionar apenas as correspondências que correspondem exatamente à linha inteira (de man grep , thx a Kusalananda :

grep -x -e "ab" -e "cd" file

A saída será:

ab
cd
ab

Ou (assumindo que o GNU grep ou compatível como \| não seja um operador BRE padrão):

grep "^\(ab\|cd\)$" file

O mesmo com o GNU sed :

sed '/^\(ab\|cd\)$/!d' file
    
por 27.10.2017 / 09:49
1

Uso:

IFS='
' # to join "$*" with newline
grep -e "$*" < file

Em grep -- "$patterns" ou grep -e "$patterns" , cada linha de $patterns é um padrão a ser procurado (ORed). (algo que você pode precisar ter em mente se algum dos padrões em "$@" for multi-linha)

Em shells POSIX, "$*" é a concatenação dos parâmetros posicionais com o primeiro caractere de $IFS .

Adicione a opção -x se você quiser que os padrões correspondam às linhas e x actly (ao contrário das substrings dentro da linha).

Observe que as linhas que correspondem a ab e cd (sem -x ) serão impressas apenas uma vez, o que seria outra diferença em relação à sua abordagem de múltiplas passagens. Se você quiser que eles sejam impressos uma vez para cada padrão de correspondência, use awk :

awk '
  BEGIN {
    for (i = 1; i < ARGC; i++) pattern[ARGV[i]]
    ARGC = 1
  }
  {for (p in pattern) if ($0 ~ p) print}' "$@" < file

Observe, entretanto, que awk padrões são expressões regulares estendidas (como em grep -E ) em oposição às expressões regulares básicas compreendidas por grep sem -E (por exemplo, x+ corresponderia a x+ com grep , mas em um ou mais x es com awk ).

    
por 27.10.2017 / 10:06