Use o bash para extrair o número entre colchetes

3

Meu arquivo é assim:

[581]((((((((501:0.00024264,451:0.00024264):0.000316197,310:0.000558837):0.00857295,((589:0.000409158,538:0.000409158):0.000658084,207:0.00106724
):0.00806454):0.0429702,(((198:0.00390205,91:0.00390205):0.016191,79:0.0200931):0.0147515,(187:0.00133008,50:0.00133008):0.0335145):0.0172574):0.
127506,((140:0.00253019,117:0.00253019):0.0533693,(((533:0.00728707,(463:8.80494e-05,450:8.80494e-05):0.00719902):0.0217722,389:0.0290593):0.0253
931,(((141:0.018004,107:0.018004):0.0143861,(111:0.00396127,(106:0.00161229,12:0.00161229):0.00234898):0.0284289):0.0145736,(129:0.0195982,((123:
0.0105973,66:0.0105973):0.0084867,10:0.019084):0.000514243):0.0273656):0.00748854):0.00144709):0.123708):0.000944439,((181:0.00108761,71:0.00108761):0.0819772);  
[50]((((((((501:0.00024264,451:0.00024264):0.000316197,310:0.000558837):0.00857295,((589:0.000409158,538:0.000409158):0.000658084,207:0.00106724):0.00806454):0.0429702,(((198:0.00390205,91:0.00390205):0.016191,79:0.0200931):0.0147515,(187:0.00133008,50:0.00133008):0.0335145):0.0172574):0.127506,((140:0.00253019,117:0.00253019):0.0533693,(((533:0.00728707,(463:8.80494e-05,450:8.80494e-05):0.00719902):0.0217722,389:0.0290593):0.0253931,(((141:0.018004,107:0.018004):0.0143861,(111:0.00396127,(106:0.00161229,12:0.00161229):0.00234898):0.0284289):0.0145736,(129:0.0195982,((123:0.0105973,66:0.0105973):0.0084867,10:0.019084):0.000514243):0.0273656):0.00748854):0.00144709):0.123708):0.000944439,((181:0.00108761,71:0.00108761):0.0819772);

Toda nova linha começa com o padrão [number] . Cada linha termina com o padrão ); .

Eu preciso extrair os números entre colchetes do início de cada linha e gravá-los em um novo arquivo. Não sei quantas linhas o arquivo tem de antemão.

    
por user3069326 08.05.2015 / 11:47

6 respostas

11

Você pode conseguir isso com apenas um único grep comando. Isso ocorre porque o GNU grep permite que você use uma expressão regular Perl ( -P ), que suporta asserções de lookaround com largura zero ( \K e (?= ) , neste caso ):

grep -oP '^\[\K\d+(?=\])' infile

Como escrito, isso enviará a saída para o seu terminal. Para redirecionar para um arquivo, use:

grep -oP '^\[\K\d+(?=\])' infile > outfile

Este método tem a vantagem de brevidade e simplicidade. Corresponde ao texto que

  • é precedido por ( \K )

    • um caractere [ ( \[ ) - \ é necessário, pois [ tem um significado especial em expressões regulares
    • que aparece no início de uma linha ( ^ );
  • consiste em um ou mais dígitos ( + ) ( \d );

  • é seguido por ( (?= ) )

    • um caractere ] ( \] ) - como com [ , \ forces ] a ser correspondido literalmente.
por Eliah Kagan 08.05.2015 / 14:38
7

Usando sed :

  • < inputfile sed -n 's/^\[\([0-9]*\)\].*$//p' > out

Resumo dos comandos :

  • < inputfile : redireciona o conteúdo de inputfile para stdin
  • -n : suprime a saída
  • > out : redireciona o conteúdo de stdout para out

Divisão do Regex :

  • s : realiza uma substituição
  • / : inicia o regex
  • ^ : corresponde ao início da linha
  • \[ : corresponde a um caractere [
  • \( : inicia o grupo de captura
  • [0-9]* : corresponde a qualquer número de dígitos
  • \) : pára o grupo de captura
  • \] : corresponde a um caractere ]
  • .* : corresponde a qualquer número de qualquer caractere
  • $ : corresponde ao final da linha
  • / : pára a regex / inicia a substituição
  • : substitui pelo primeiro grupo de captura
  • / : interrompe a substituição
  • p : imprime apenas as linhas correspondentes

Usando grep + tr (se você precisar de um método que seja executado tanto no Ubuntu quanto em outro SO cujo grep não suporte o PCRE - caso contrário, consulte Versão grep -only de Eliah Kagan:

  • < inputfile grep -o '^\[[0-9]*\]' | tr -d '[]' > out

Resumo dos comandos :

  • < inputfile in grep : redireciona o conteúdo de inputfile para stdin
  • -o in grep : imprime apenas a correspondência
  • -d in tr : exclui os caracteres
  • > out in tr : redireciona o conteúdo de stdout para out

Divisão do Regex :

  • ^ : corresponde ao início da linha
  • \[ : corresponde a um caractere [
  • [0-9]* : corresponde a qualquer número de dígitos
  • \] : corresponde a um caractere ]
por kos 08.05.2015 / 12:03
3

a perl way:

perl -ne 'print "$1\n" if /^\[([0-9]*)\].*/' testdata > out

ou com awk :

awk 'match($0, /^\[[0-9]*\]/) {print substr($0, RSTART + 1, RLENGTH - 2)}' testdata > out

Usado o Regex nos dois casos:

^\[[0-9]*\]

Explicação

  • /^\[[0-9]*\]/

    • ^ afirma a posição no início da string

    • \[ corresponde ao caractere [ literalmente

    • [0-9]* corresponde a um único caractere presente na lista abaixo

      • Quantificador: * Entre zero e ilimitado vezes, tantas vezes quanto possível, devolvendo conforme necessário [ganancioso]

      • 0-9 um único caractere no intervalo entre 0 e 9

    • \] corresponde ao caractere ] literalmente

    Demonstração do Debuggex

por A.B. 08.05.2015 / 14:47
2

Use isso no Bash:

 grep -oh '\[[0-9].*\]' mytestfile | sed 's/.*\[\([^]]*\)\].*//g' > myresultfile
    
por Frantique 08.05.2015 / 12:00
1

python solution usando o módulo re e considerando duas situações:

#!/usr/bin/env python2
import re
with open('/path/to/file.txt') as f:
    for line in f:
        digits_case_1 = re.search(r'(?<=^\[)\d+(?=\])', line)
        digits_case_2 = re.search(r'(?<=^\[)\d+(?=\].*\);$)', line)
        if digits_case_1:
            print 'Not considering ");" at end: ' + digits_case_1.group()
        if digits_case_2:
            print 'Considering ");" at end: ' + digits_case_2.group()

Saída:

Not considering ");" at end: 581
Not considering ");" at end: 50
Considering ");" at end: 50

Aqui eu considerei duas situações, pois sua pergunta não parece clara para mim.

  • digits_case_1 imprimirá a correspondência de dígitos entre [] no início da linha, não considerará se a linha está terminando com ); ou não.

  • digits_case_2 imprimirá dígitos entre [] no início da linha apenas se a linha terminar com ); .

por heemayl 08.05.2015 / 19:23
0

cat $FILE | awk -F\] '{ print $1 }' | grep '\[' | tr -d '['

Onde a progressão é: §

$ FILE=/tmp/tmp.tmp

$ cat $FILE
[581]((((((((501:0.00024264,451:0.00024264):0.000316197,310:0.000558837):0.00857295,((589:0.000409158,538:0.000409158):0.000658084,207:0.00106724
):0.00806454):0.0429702,(((198:0.00390205,91:0.00390205):0.016191,79:0.0200931):0.0147515,(187:0.00133008,50:0.00133008):0.0335145):0.0172574):0.
127506,((140:0.00253019,117:0.00253019):0.0533693,(((533:0.00728707,(463:8.80494e-05,450:8.80494e-05):0.00719902):0.0217722,389:0.0290593):0.0253
931,(((141:0.018004,107:0.018004):0.0143861,(111:0.00396127,(106:0.00161229,12:0.00161229):0.00234898):0.0284289):0.0145736,(129:0.0195982,((123:
0.0105973,66:0.0105973):0.0084867,10:0.019084):0.000514243):0.0273656):0.00748854):0.00144709):0.123708):0.000944439,((181:0.00108761,71:0.00108761):0.0819772);
[50]((((((((501:0.00024264,451:0.00024264):0.000316197,310:0.000558837):0.00857295,((589:0.000409158,538:0.000409158):0.000658084,207:0.00106724):0.00806454):0.0429702,(((198:0.00390205,91:0.00390205):0.016191,79:0.0200931):0.0147515,(187:0.00133008,50:0.00133008):0.0335145):0.0172574):0.127506,((140:0.00253019,117:0.00253019):0.0533693,(((533:0.00728707,(463:8.80494e-05,450:8.80494e-05):0.00719902):0.0217722,389:0.0290593):0.0253931,(((141:0.018004,107:0.018004):0.0143861,(111:0.00396127,(106:0.00161229,12:0.00161229):0.00234898):0.0284289):0.0145736,(129:0.0195982,((123:0.0105973,66:0.0105973):0.0084867,10:0.019084):0.000514243):0.0273656):0.00748854):0.00144709):0.123708):0.000944439,((181:0.00108761,71:0.00108761):0.0819772);

$ cat $FILE | awk -F\] '{ print $1 }'
[581
):0.00806454):0.0429702,(((198:0.00390205,91:0.00390205):0.016191,79:0.0200931):0.0147515,(187:0.00133008,50:0.00133008):0.0335145):0.0172574):0.
127506,((140:0.00253019,117:0.00253019):0.0533693,(((533:0.00728707,(463:8.80494e-05,450:8.80494e-05):0.00719902):0.0217722,389:0.0290593):0.0253
931,(((141:0.018004,107:0.018004):0.0143861,(111:0.00396127,(106:0.00161229,12:0.00161229):0.00234898):0.0284289):0.0145736,(129:0.0195982,((123:
0.0105973,66:0.0105973):0.0084867,10:0.019084):0.000514243):0.0273656):0.00748854):0.00144709):0.123708):0.000944439,((181:0.00108761,71:0.00108761):0.0819772);
[50

$ cat $FILE | awk -F\] '{ print $1 }' | grep '\['
[581
[50

$ cat $FILE | awk -F\] '{ print $1 }' | grep '\[' | tr -d '['
581
50

$

§ Para aqueles sem acesso ao comando man .

    
por boardrider 08.05.2015 / 15:51