Como posso extrair nomes de pdf de um arquivo de log lftp?

2

Eu tenho um log assim:

2016-05-11 07:09:54 ftp://[email protected]/test1/fool/1999/How/05%20May/test160511.pdf -> /test/keep/more/use/05/test160511.pdf 0-28442281 33.5 KiB/s

eu preciso extrair apenas "test160511.pdf" e colocar em arquivo de log separado.

É possível?

    
por Rumpelstiltskin 11.05.2016 / 09:18

3 respostas

1

Em um one-liner de python:

python3 -c '[print(p+".pdf") for p in [s.split(".pdf")[0] for s in open("logfile").read().split("/") if ".pdf" in s]]'

em que "logfile" é o caminho para o seu arquivo de log, entre aspas duplas. Um exemplo, usando a entrada da sua pergunta, em que /home/jacob/Bureaublad/pd.txt é meu arquivo de log:

$ python3 -c '[print(p+".pdf") for p in [s.split(".pdf")[0] for s in open("/home/jacob/Bureaublad/pd.txt").read().split("/") if "pdf" in s]]'
test160511.pdf
test160511.pdf

Explicação

O comando:

  • divide o conteúdo do arquivo pelo dellimeter / (barra):

    open("logfile").read().split("/") 
    

    e procura as seções que contêm pdf :

    for s in open("/home/jacob/Bureaublad/pd.txt").read().split("/") if "pdf" in s
    
  • Subsequentemente, divide as strings encontradas pelo dellimeter .pdf e mantém a primeira seção, que é a seção entre / e pdf .

  • subsequentemente, a extensão é adicionada:

    print(p+".pdf")
    

Desta forma, o nome do arquivo do pdf é sempre recuperado corretamente, mesmo que o nome do arquivo (pdf-) contenha espaços.

Apenas nomes de arquivos exclusivos?

Se você não quiser repetir nomes de arquivos com várias ocorrências:

python3 -c '[print(p+".pdf") for p in set([s.split(".pdf")[0] for s in open("logfile").read().split("/") if "pdf" in s])]'

Do mesmo exemplo:

$ python3 -c '[print(p+".pdf") for p in set([s.split(".pdf")[0] for s in open("/home/jacob/Bureaublad/pd.txt").read().split("/") if "pdf" in s])]'
test160511.pdf
    
por Jacob Vlijm 11.05.2016 / 09:55
3

Usando grep com PCRE ( -P ):

grep -Po '.*/\K[^\s]+(?=\s+->)'

Exemplo:

$ grep -Po '.*/\K[^\s]+(?=\s+->)' <<<'2016-05-11 07:09:54 ftp://[email protected]/test1/fool/1999/How/05%20May/test160511.pdf -> /test/keep/more/use/05/test160511.pdf 0-28442281 33.5 KiB/s'
test160511.pdf

Ou sed :

sed -r 's#.*/([^[:blank:]]+)[[:blank:]]+->.*##'

Exemplo:

$ sed -nr 's#.*/([^[:blank:]]+)[[:blank:]]+->.*##p' <<<'2016-05-11 07:09:54 ftp://[email protected]/test1/fool/1999/How/05%20May/test160511.pdf -> /test/keep/more/use/05/test160511.pdf 0-28442281 33.5 KiB/s'
test160511.pdf

Você pode salvar a saída usando o operador de redirecionamento de saída > :

grep .... >/where/to/save.log

Então, neste caso:

grep -Po '.*/\K[^\s]+(?=\s+->)' <<<'your_string' >output.log

Você também pode usar uma variável intermediária:

temp=$(grep -Po '.*/\K[^\s]+(?=\s+->)' <<<'your_string')

e, em seguida, salve:

echo "$temp" >output.log
    
por heemayl 11.05.2016 / 09:26
3

Outra grep solution ( file contém o exemplo da sua pergunta):

$ grep -oP '/\K[^/]+\.pdf' file
test160511.pdf
test160511.pdf

Apenas para nomes exclusivos:

$ grep -oP '/\K[^/]+\.pdf' file | sort -u
test160511.pdf

Explicação

  • -o : imprime apenas a parte correspondente da linha.
  • -P : use expressões regulares compatíveis com Perl (PCRE)
  • /\K[^/]+\.pdf : corresponde a / e, em seguida, descarta-o (é o que faz o \K , assim o / não é incluído na saída). Em seguida, corresponda um ou mais caracteres que não sejam / ( [^/]+ ), seguidos por .pdf . O . significa "qualquer caractere" em expressões regulares, portanto, para corresponder a um literal . , você precisa escapar: \.
  • sort -u : imprima apenas linhas exclusivas.
por terdon 11.05.2016 / 12:30