extrai texto de um arquivo usando terminal?

1

Eu quero processar o corpo do texto e extrair um inteiro de uma posição específica no texto, mas não sei como descrever essa 'posição particular'. Expressões regulares realmente me confundem. Passei algumas horas lendo tutoriais e não me sinto mais perto de uma resposta: (

Há um monte de texto que pode ou não incluir números inteiros (que eu não quero) e depois há uma linha que sempre contém

id_ad=1929170&action

e, em seguida, seguido por um monte de lixo que eu não me importo, mais uma vez pode ou não incluir um ou mais números inteiros.

Então intuitivamente eu sei que eu só quero ignorar tudo (e inclusive) id_ad= e ignorar tudo depois (e inclusive) &action e ficarei com o inteiro que eu quero. E sei que posso usar expressões regulares para conseguir isso. Mas eu não consigo descobrir isso.

Eu gostaria de fazer isso como um forro do terminal, se possível.

    
por bcsteeve 06.11.2014 / 20:54

4 respostas

2

Não muito um forro (embora o comando para executá-lo seja um forro :)), mas aqui está uma opção em python:

#!/usr/bin/env python3
import sys
file = sys.argv[1]

with open(file) as src:
    text = src.read()

starters = [(i+6, text[i:].find("&action")+i) for i in range(len(text)) if text[i:i+6] == "id_ad="]
if len (starters) > 0:
    for item in starters:
        print(text[item[0]:item[1]])

O script primeiro lista todas as ocorrências (índices) da string (start) "id_ad=", em combinação com a string "& amp; action" (final). Em seguida, imprime tudo o que existe entre esses "marcadores".

Extraído de um arquivo preparado:

"Eu quero processar o corpo do texto e extrair um inteiro de uma posição específica no texto, mas não sei como descrever essa 'posição particular'. Expressões regulares realmente me confundem. Passei (desperdiçado) algumas horas lendo tutoriais e não me sinto mais perto de uma resposta :( Há um monte de texto que pode ou não incluir números inteiros (que eu não quero) e, em seguida, há uma linha que sempre contém id_ad = 1929170 & amp; action Há um monte de texto que pode ou não incluir números inteiros (que eu não quero) e, em seguida, há uma linha que sempre contém id_ad = 1889170 & amp; action e, em seguida, seguido por um monte de lixo com o qual não me importo, pode ou não incluir um ou mais números inteiros. Há um monte de texto que pode ou não incluir números inteiros (que eu não quero) e, em seguida, há uma linha que contém sempre id_ad = 1889170 & ação e, em seguida, seguido por um monte de lixo que não me interessa, novamente pode ou não incluir um ou mais números inteiros. Há um monte de texto que pode ou não incluir números inteiros (que eu não quero) e, em seguida, há uma linha que sempre contém id_ad = 1929990 & amp; action "

O resultado é:

1929170
1889170
1889170
1929990

Como usar

Cole o script em um arquivo vazio, salve-o como extract.py , execute-o pelo comando:

python3 <script> <file>

Nota

Se houver apenas uma ocorrência no arquivo de texto, o script poderá ser muito mais curto:

#!/usr/bin/env python3
import sys
file = sys.argv[1]

with open(file) as src:
    text = src.read()
print(text[text.find("id_ad=")+6:text.find("&action")])
    
por Jacob Vlijm 06.11.2014 / 21:46
2

Por exemplo:

 egrep "id_ad=[[:digit:]]+&action" file.txt |  tr "=&" "  " | cut -d " " -f2 

... mas tenho certeza que existem maneiras mais elegantes ;-).

Passo a passo:

egrep "id_ad=[[:digit:]]+&action" file.txt 

digitalize file.txt para o padrão (expressão regular) composto por um literal id_ad= , seguido por 1 ou mais dígitos (o significado de [[:digit:]]+ , seguido por um literal &action . Envie a saída para saída padrão.

tr "=&" "  " 

transforma os caracteres "=" e "& amp;" em dois espaços.

cut -d " " -f2

imprime o segundo campo (separado por espaço) da entrada padrão.

    
por Rmano 06.11.2014 / 21:03
2

Com sed:

sed 's/id_ad=\(.*\)&action//' filename

Explicação:

O comando Above retorna todas as strings ( .* ) entre duas palavras START ( id_ad= ) e END word ( &action ) no nome do arquivo.
\(...\) É usado para capturar grupos. \( é o início de um grupo de captura e termina com \) . E com imprimimos o índice do seu grupo (temos um grupo de captura)

O comando sed melhor para a solução acima pode ser assim:

sed 's/^id_ad=\([0-9]*\)&action//' filename

^ Início da linha.
[0-9]* : Qualquer número com 0 ou mais ocorrências.
Veja mais sobre o comando sed

Com o grep:

Explicação:

grep -Po '(?<=id_ad=)[0-9]*(?=&action)' filename

Do homem grep:

-o, --only-matching
      Print only the matched (non-empty) parts of a matching line,
      with each such part on a separate output line.
-P, --perl-regexp
      Interpret PATTERN as a Perl compatible regular expression (PCRE)

Retorna qualquer número com 0 ou mais ocorrências ( [0-9]* ) entre duas palavras START ( id_ad= ) e END word ( &action ) no nome do arquivo.

(?<=pattern) : lookbehind positivo. Um par de parênteses, com o parêntese de abertura seguido por um ponto de interrogação, símbolo "menor que" e um sinal de igual.

(?<=id_ad=)[0-9]* (lookbehind positivo) corresponde a 0 ou mais ocorrências de números que se seguiram após id_ad= no nome do arquivo.

(?=pattern) : Lookahead positivo: o constructo lookahead positivo é um par de parênteses, com o parêntese de abertura seguido por um ponto de interrogação e um sinal de igual.

[0-9]*(?=&action) : (lookahead positivo) corresponde a 0 ou mais ocorrências de números seguidos por padrão ( &action ), sem fazer com que o padrão ( &action ) faça parte da correspondência.
Leia mais sobre Lookahead e Lookbehind

Links extras:
Tópicos Avançados do Grep
GREP para Designers

    
por αғsнιη 06.11.2014 / 21:32
1

Outra resposta python através do módulo re . Exemplo roubado do post de Jacob.

script.py

#!/usr/bin/python3
import sys
import re
file = sys.argv[1]
L = []                                                  # Declare an empty list
with open(file) as src:
    for j in src:                                       # iterate through all the lines
        for i in re.findall(r'id_ad=(\d+)&action', j):  # extracts the digits which was present in-between 'id_ad=' and '&action' strings.
            L.append(i)                                 # Append the extracted digits to the already declared empty list L. 
    for f in L:                                         # Iterate through all the elements in the list L
        print(f)                                        # Print each element from the list L in a separate new line.

Execute o script acima como

python3 script.py /path/to/the/file

Exemplo:

$ cat fi
I want to process the body of text and extract an integer from a specific position in the text, but I'm not sure how to describe that 'particular position'. Regular expressions really confuse me. I spent (wasted) a couple hours reading tutorials and I feel no closer to an answer :( There's a bunch of text which may or may not include integers (that I don't want) and then there's a line that always contains

 id_ad=1929170&action There's a bunch of text which may or may not include integers (that I don't want) and then there's a line that always contains id_ad=1889170&action and then followed by a bunch of garbage I don't care about, again it may or may not include one or more integers. There's a bunch of text which may or may not include integers (that I don't want) and then there's a line that always contains

 id_ad=1889170&action and then followed by a bunch of garbage I don't care about, again it may or may not include one or more integers. There's a bunch of text which may or may not include integers (that I don't want) and then there's a line that always contains id_ad=1929990&action
$ python3 script.py ~/file
1929170
1889170
1889170
1929990
    
por Avinash Raj 08.11.2014 / 03:38