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.

Respostas:


14

Tente o seguinte:

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

ou:

perl -nle 'print $1 if /ID:.*?(\d+)/' file

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

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]*'
    

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

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

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:


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 :)


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.