Regex que grep números após seqüência específica

8

Então, eu tenho uma linha:

ID: 54376

Você pode me ajudar a criar uma regex que só retornaria números sem "ID:"?

NOTA: Essa sequência está em um arquivo.

Blake Gibbs
fonte

Respostas:

14

Tente o seguinte:

grep -oP '(?<=ID: )[0-9]+' file

ou:

perl -nle 'print $1 if /ID:.*?(\d+)/' file
cuonglm
fonte
Obrigado pela resposta, mas não preciso de todos os números de um arquivo, apenas de um número que ocorra após a identificação: #
Blake Gibbs
Atualizei minha resposta.
cuonglm
1
Observe que -oe -Psão extensões GNU para grep. -otrabalha com os BSDs também. O suporte ao PCRE -Pnem sempre é compilado.
25414 Matt
4

Use egrepcom -oou grepcom a -Eoopção para obter apenas o segmento correspondente. Use [0-9]como regex para obter apenas números:

grep -Eo [0-9]+ filename
Rohit Jain
fonte
1
O OP precisa corresponder somente após uma sequência específica. Veja o título da pergunta.
terdon
4

Existem muitas maneiras de fazer isso. Por exemplo:

  1. Use o GNU grepcom PCREs recentes e combine os números depois de ID::

    grep -oP 'ID:\s*\K\d+' file
    
  2. Use awke simplesmente imprima o último campo de todas as linhas que começam comID:

    awk '/^ID:/{print $NF}' file
    

    Isso também imprimirá campos que não são números, para obter apenas números e apenas no segundo campo, use

    awk '($1=="ID:" && $2~/^[0-9]+$/){print $2}' file
    
  3. Use o GNU grep com expressões regulares estendidas e analise-o duas vezes:

    grep -Eo '^ID: *[0-9]+' file | grep -o '[0-9]*'
    
terdon
fonte
Obrigado! O que \Kestá fazendo no primeiro exemplo?
Rd_d 14/05
2
@rnd_d é uma construção PCRE (Expressões Regulares Compatíveis com Perl), que significa "ignorar qualquer coisa que corresponda a este ponto". Ele é usado como um lookbehind, que vamos me usar -opara imprimir apenas a parte correspondente, mas também as coisas de descarte Eu não estou interessado em comparar. echo "foobar" | grep -oP "foobar"Eecho "foobar" | grep -oP 'foo\Kbar'
terdon
4
sed -n '/ID: 54376/,${s/[^ 0-9]*//g;/./p}'

Isso imprimirá apenas todos os números e espaços que ocorrerem depois ID: 54376em qualquer entrada de arquivo.

Acabei de atualizar o item acima um pouco para torná-lo um pouco mais rápido *e não criar plinhas em branco após remover os caracteres não {numéricos, espaço}.

Ele aborda linhas de regex /ID: 54376/ ,através do $passado e sobre eles s///remove todos ou quaisquer *caracteres ^não [^ 0-9]*em seguida, prints /qualquer /linha com um .carácter restante.

DEMO:

{
echo line 
printf 'ID: 54376\nno_nums_or_spaces\n'
printf '%s @nd 0th3r char@cter$ %s\n' $(seq 10)
echo 'ID: 54376'
} | sed -n '/ID 54376/,${s/[^ 0-9]*//g;/./p}'

RESULTADO:

 54376
1  03  2
3  03  4
5  03  6
7  03  8
9  03  10
 54376
mikeserv
fonte
1

Usando sed:

{
    echo "ID: 1"
    echo "Line doesn't start with ID: "
    echo "ID: Non-numbers"
    echo "ID: 4"
} | sed -n '/^ID: [0-9][0-9]*$/s/ID: //p'

O -né "não imprime nada por padrão", o /^ID: [0-9][0-9]*$/é "para linhas que correspondem a este regex" (começa com "ID:", depois 1 ou mais dígitos e, em seguida, fim de linha), e o s/ID: //pé do formulário s/pattern/repl/flags- ssignifica que está substituindo, para substituir o padrão "ID: "pelo texto de substituição ""(sequência vazia) usando a pbandeira, o que significa "imprima esta linha depois de fazer a substituição".

Resultado:

1
4
godlygeek
fonte
Não funcionará se o ID estiver presente no centro de uma linha.
Avinash Raj
Nem deveria, com base na minha leitura da pergunta. E não tentar lidar prematuramente com esse caso torna o código mais simples e mais portátil.
30914 godlygeek
0

Outro comando GNU sed,

sed -nr '/ID: [0-9]+/ s/.*ID: +([0-9]+).*/\1/p' file

Imprime qualquer número após ID:

Avinash Raj
fonte
Você realmente não precisa do +. Se a diferença entre um personagem e 3 caracteres é o seu script pode não funcionar em todos seds você provavelmente deve fazer: sed -n '/ID: \([0-9][0-9]*\).*/{s//\1/;s/.*[^0-9]//;/./p}'. Sua resposta também perde a primeira ID: [0-9]em uma linha contendo duas ocorrências de ID: [0-9].
mikeserv
0

Use grep + awk:

  grep "^ID" your_file | awk {'print $2'}

Bônus: fácil de ler :)

lírio
fonte
1
Você não precisa grepse estiver usando awk. awk '/^ID/ { print $2 }'faz a mesma coisa e evita problemas de buffer de linha grep . Também é praticamente o mesmo que uma das soluções na resposta do @ terdon.
12286