Como posso recuperar e-mails e sites de arquivos csv na linha de comando?

2

Tenho muitos arquivos .csv (alguns convertidos de xlsx ) e estou tentando extrair e-mails e sites desses arquivos.

Os dados nos arquivos se parecem com:

Daniel,Rose,[email protected],http://www.example.com,1234567890
Daniel1,Rose,[email protected],http://www.example.com,1234567890
Daniel2,Rose,[email protected],http://example.com,1234567890
Daniel3,Rose,[email protected],www.example.com,1234567890
Daniel4,Rose,[email protected],1234567890,example.com

Eu só quero extrair os e-mails e os sites com o cliente nesse csv.
A saída deve ficar assim:

[email protected]
http://www.example.com 
[email protected]
http://www.example.com
[email protected]
www.example.com
[email protected]
    
por Jaffer Wilson 02.02.2017 / 13:31

2 respostas

4

Uma opção em Python baseada em texto simples, definitivamente mais detalhada:

#!/usr/bin/env python3
import sys

f = sys.argv[1]; out = sys.argv[2]

with open(out, "wt") as wr:
    with open(f) as read:
        for l in read:
            for s in l.strip().split(","):
                if any(["@" in s, "www" in s, "http" in s]):
                    wr.write(s+"\n")

Ou, apenas por diversão, um pouco mais comprimido:

#!/usr/bin/env python3
import sys

with open(sys.argv[2], "wt") as wr:
    with open(sys.argv[1]) as read:
        [[wr.write(s+"\n") for s in l.strip().split(",") if any(["@" in s, "www" in s, "http" in s])] for l in read]

Para usar

  • Copie o script em um arquivo vazio, salve-o como get_stuff.py
  • Execute-o com o arquivo de origem e o arquivo de saída de destino como argumentos:

    python3 /path/to/get_stuff.py <input_file> <output_file>
    

Resultado:

[email protected]
http://www.example.com
[email protected]
http://www.example.com
[email protected]
[email protected]
www.example.com
[email protected]

Comparação no tempo

É interessante notar que em arquivos menores (como no exemplo), a opção sed é mais rápida, mas em arquivos maiores a opção python é mais rápida:

em um arquivo de 150.000 linhas:

sed

real    0m0.073s
user    0m0.068s
sys     0m0.000s

python

real    0m0.046s
user    0m0.044s
sys     0m0.000s

Em um arquivo de 10 linhas:

sed

real    0m0.003s
user    0m0.000s
sys     0m0.000s

python

real    0m0.037s
user    0m0.032s
sys     0m0.000s

(Eu deveria mencionar que tenho uma caixa antiga, todos os tempos devem ser mais curtos em uma máquina séria)

A ideia pode ser que especialmente se você precisar extrair dados de muitos arquivos menores em um loop, use sed, em arquivos maiores em um loop, use python.

Em um único arquivo, pequeno ou grande, a diferença entre 0.073 e 0.046 é totalmente irrelevante.

Além disso

Abaixo de uma versão para extrair os mesmos dados de um diretório inteiro (simples) de arquivos.

#!/usr/bin/env python3
import sys
import os

dr = sys.argv[1]

def extract(f, out):
    with open(out, "wt") as wr:
        with open(f) as read:
            [[wr.write(s+"\n") for s in l.strip().split(",") if any(
                ["@" in s, "www" in s, "http" in s]
                )] for l in read]

for file in os.listdir(dr):
    f = os.path.join(dr, file); out = os.path.join(dr, "extracted_"+file)
    extract(f, out)

De cada um dos arquivos, o script criará um novo arquivo com os dados extraídos. De um arquivo:

somefile.csv

ele criará um segundo arquivo, chamado:

extracted_somefile.csv
    
por Jacob Vlijm 02.02.2017 / 15:08
3

Eu sinto que sua saída desejada está faltando 2 linhas?

$ sed -r 's|.*,([^,]+@[^0-9]+),.*||' file | tr ',' '\n'
[email protected]
http://www.example.com
[email protected]
http://www.example.com
[email protected]
http://example.com
[email protected]
www.example.com
[email protected]

Se não, então, por favor, esclareça.

Explicação

  • -r use ERE
  • s|old|new| replace old com new
  • .*, qualquer caractere que termine com vírgula
  • ([^,]+@[^0-9]+),.* salva alguns caracteres não-comma antes de um @ , depois alguns caracteres que não são números antes de uma vírgula - corresponde a qualquer coisa depois disso para que possamos descartá-lo
  • backreference para o padrão salvo
  • tr ',' '\n' altera as vírgulas restantes em novas linhas (recorri ao encanamento para tr porque os campos não são consistentes, mas provavelmente podem ser evitados com inteligência)
por Zanna 02.02.2017 / 13:49