Grep: como adicionar uma condição "OR"? [duplicado]

24

Como posso introduzir um OR condicional no grep? Algo como, digitando um tipo de arquivo para (JPEG ou JPG) e, em seguida, enviando apenas os arquivos para a pasta de fotos. Por exemplo. Eu sei como enviar o arquivo onde eu quero, e obter o tipo de arquivo, só preciso de ajuda com a parte do grep.

Eu estou no OS X, que parece ter modificado / customizado * nix utilitários do que o que eu estou acostumado em um ambiente * nix. Então esperamos que as respostas sejam tão genéricas / portáteis quanto possível.

    
por Harv 01.12.2011 / 00:41

5 respostas

26

Eu também sou relativamente novo no regex, mas como ninguém respondeu, vou tentar. O operador de tubos "|" é usado para um operador OR.

O seguinte REGEX deve levá-lo a algum lugar.

.+((JPG)$|(JPEG)$)

(Combine qualquer coisa uma ou mais vezes seguido por "JPG" ou "JPEG" no final)

Resposta estendida (editada depois de aprender um pouco sobre (e) grep): Supondo que você tenha uma pasta com os seguintes arquivos:

test.jpeg, test.JpEg, test.JPEG, test.jpg, test.JPG, test.notimagefile, test.gif

(não é criativo com nomes ...)

Primeiro, começamos definindo o que sabemos sobre nosso padrão:    Sabemos que estamos procurando o final do nome. Logo, usamos o operando "$" para definir que cada linha deve terminar com o padrão definido.    Sabemos que o padrão precisa ser JPEG ou JPG. Para isso, usamos o pipeline "|" como um ou operando.    Nosso padrão é agora:

((JPEG)|(JPG))$

(Corresponder a qualquer linha que termine com "JPEG" ou "JPG")

No entanto, vemos que neste exemplo, a única diferença é o opcional "E". Para isso, podemos usar o "?" operando (que significa opcional).    Nós escrevemos:

(JP(E)?G)$

(Mach qualquer arquivo que termine com um padrão como: "J", seguido por "P", seguido por um opcional "E", seguido por um "G").

No entanto, também gostaríamos de corresponder arquivos com letras minúsculas no nome do arquivo. Para isso, apresentamos a classe de caracteres "[...]". significado corresponde a um dos seguintes.    Nós escrevemos:

([jJ][pP]([eE])?[gG])$

(Combine qualquer arquivo que termine com um padrão como: "j" ou "J", seguido por "p" ou "P", seguido por um opcional "e" ou "E", seguido por "g" ou " G ") (Isso também pode ser feito usando a opção "-i" no grep, mas eu tomei isso como um exercício no REGEX)

Finalmente, uma vez que (esperamos) começarmos a ver um padrão, podemos omitir os parênteses desnecessários. Como há apenas uma letra opcional ("E"), podemos omitir essa. Além disso, como o arquivo só tem esse padrão para terminar, podemos omitir os parênteses inicial e final. Assim, nós simplesmente conseguimos:

[jJ][pP][eE]?[gG]$

Finalmente; vamos supor que você também queira encontrar arquivos com o tipo ".gif", podemos adicionar isso como um segundo parâmetro:

 ([jJ][pP][eE]?[gG])|([gG][iI][fF])$

(Aqui eu adicionei novamente parênteses extras para legibilidade / agrupamento. Sinta-se livre para removê-los se eles parecerem ofuscantes.)

Finalmente, usei ls e um pipeline para enviar todos os nomes de arquivos para (e) grep:

ls | egrep '([jJ][pP][eE]?[gG])|([gG][iI][fF])$' 

Resultado:

test.gif
test.JPG
test.JpEg
test.JPEG
test.jpg
test.JPG

Segunda edição:    Usando a opção -i e omitindo parênteses, podemos reduzi-lo para apenas:

ls | egrep -i 'jpe?g|gif$'
    
por 01.12.2011 / 00:56
24

Se você quiser introduzir um OR no grep, apresentá-lo com o REGEXP é o caminho errado. Experimente a opção -e no grep:

grep -e PATTERN1 -e PATTERN2 your_file

corresponderá às linhas com PATTERN1 ou PATTERN2.

    
por 18.12.2011 / 15:27
11

Se você quiser corresponder arquivos por seus nomes, grep é a ferramenta errada. O utilitário grep procura por padrões dentro de arquivos; é irrelevante se você se importa com o nome do arquivo.

Padrões de caractere curinga da shell são a maneira de corresponder arquivos por seus nomes. Nos shells modernos, os padrões de caracteres curinga têm o mesmo poder expressivo das expressões regulares (ou seja, o que você pode fazer com um, você pode fazer com o outro), mas eles têm uma sintaxe diferente por motivos históricos.

No bash, você precisa ativar os padrões de curingas estendidos primeiro, digitando esta linha ou colocando-a em seu ~/.bashrc :

shopt -s extglob

Em seguida, você pode mover todos os arquivos .jpg ou .jpeg do atual para um diretório de fotos como este:

mv *.@(jpg|jpeg) /path/to/photo/directory

ou até mesmo

mv *.jp?(e)g /path/to/photo/directory

Em zsh, você pode usar a sintaxe acima se você colocar setopt ksh_glob no seu ~/.zshrc (ou digitá-lo na linha de comando), ou você pode escrever

mv *.(jpg|jpeg) /path/to/photo/directory
mv *.jp(e|)g /path/to/photo/directory

Se você deseja copiar arquivos do diretório atual e de seus subdiretórios recursivamente, então em zsh você pode escrever

mv **/*.(jpg|jpeg) /path/to/photo/directory

(Observe que isso copia foo/bar.jpg para /path/to/photo/directory/bar.jpg .) Na versão bash 4, execute shopt -s globstar e você pode escrever

mv **/*.@(jpg|jpeg) /path/to/photo/directory
    
por 01.12.2011 / 03:19
8

você está obtendo o tipo de arquivo executando file $file e vendo a saída?

tk-mbp:~ tkennedy$ file share/rally.jpg 
share/rally.jpg: JPEG image data, JFIF standard 1.01

ou, você está apenas olhando para a extensão do arquivo?

Se você está vendo o tipo de arquivo real na saída do comando file:

for file in $(find $dir -type f -exec file {} \; | grep JPEG | cut -d: -f1); do mv $file $photo_dir/ ; done

Se você está apenas olhando para a extensão do arquivo, você pode fazer tudo em find :

find $dir -type f -name \*jpg -o -name \*jpeg -o -name \*JPG -o -name \*JPEG -exec mv {} $photo_dir/ \;

Se você quer apenas saber como passar vários argumentos para o grep, você pode fazer isso usando egrep ou grep -E no Mac OS X.

find $dir | grep -E 'jpg|jpeg|JPG|JPEG'

etc.

    
por 01.12.2011 / 01:35
1

Aqui está outra maneira de fazer isso:

grep "foo\|bar" /path/to/file

Encontre o texto foo ou bar em file

    
por 02.03.2016 / 14:01

Tags