Grep para uma linha contendo apenas 5 ou 6 números

3

Como você escolheria uma linha contendo apenas 5 ou 6 números? Algo assim.

caso 1 (tem espaço na liderança)

           10      2       12      1       13

caso 2 (sem espaço à esquerda)

   1       2       3       4       5        6

Eu pensei que algo assim funcionaria.

grep -E '[0-9]{5}'
    
por cokedude 04.12.2014 / 07:50

7 respostas

6

grep -E '[0-9]{5}' está procurando números com pelo menos 5 dígitos. O que você precisa é de 5 números com pelo menos um dígito:

grep -E '[0-9]+([^0-9]+[0-9]+){4}'
  • [0-9]+ - um número de pelo menos um dígito
  • [^0-9]+[0-9]+ - um número com pelo menos um dígito, precedido por pelo menos um caractere não digitável. Em seguida, repetimos isso 4 vezes para obter 5 números separados por não dígitos.
  • Se o requisito for exatamente 5, convém cercar essa regex com [^0-9] para que a linha inteira seja correspondida (com as âncoras, é claro).
  • Dependendo do que você deseja aqui (o 1,2,3,4,6 qualifica?), você pode procurar outros separadores. Por exemplo, um número real de notação científica adequada seria semelhante: [+-]?(([0-9]+(\.[0-9]+)?)|([0-9]?\.[0-9]+))([eE][+-][0-9]+)? Portanto, os separadores podem não incluir . , e , etc. Eles podem ser apenas whitespace, como mikeserv notes. Ou talvez vírgulas, se é um registro CSV. Ou, dependendo da localidade, uma vírgula seria o separador decimal. Varie [^0-9] conforme sua necessidade.
por 04.12.2014 / 08:05
2

Eu usaria algo um pouco mais poderoso que grep . Isso pode ser feito em perl:

perl -ne 'print if s/\d+/$&/g == 5' your_file

A substituição regex substitui todos os grupos de um ou mais dígitos ( \d+ ) por si ( $& ): não faz nada. Ele é usado apenas para efeito colateral, pois o operador s/// retorna o número de vezes que ele conseguiu substituir seu regex. Assim, a linha é impressa somente se s/// encontrou 5 grupos de dígitos.

    
por 04.12.2014 / 07:57
2

Outro perl :

$ perl -MList::Util=first -Tnle '
  s/^\s+|\s+$//g;
  @e = split /\s+/;
  print if @e == 5 || @e == 6 and !first {/\D/} @e;
' file
10      2       12      1       13

Explicação

  • s/^\s+|\s+$//g aparar a linha.

  • @e = split /\s+/ divide a linha no array @e .

  • Nós imprimiremos a linha se:

    • array @e contém 5 ou 6 elementos.
    • E Nenhum de seus elementos contém caracteres não dígitos ( \D correspondem a caracteres não dígitos).
por 04.12.2014 / 08:26
2
grep -E '^(\s*[0-9]+\s+){4,5}[0-9]+\s*$'
    
por 04.12.2014 / 16:50
2
awk '{l=$0; n = gsub(/[0-9]+/, "", l)}; n == 5 || n == 6' 

(mesmo princípio da resposta de Joseph )

    
por 04.12.2014 / 16:08
0

Uma maneira com o awk que é personalizável para diferentes números de campos.
Também o espaço em branco não importa.

awk 'NF~/^(5|6)$/{x=0;for(i=1;i<=NF;i++)x+=($i~/^[0-9]+$/)}x==NF' file

Isso verifica se o número de campos é 5 ou 6, embora seja possível adicionar mais números de campos se os seus requisitos forem alterados.

Em seguida, define um contador para 0

Em seguida, os loops que verificam cada campo são um número e se adicionar 1 ao contador

Se o contador for igual ao número de campos, a linha será impressa.

exemplo

input

  1       2       3       4       5        6
        2       3       4       5        6
3       4       5        6
blah  1       2       3       4       5
      4       3324       4       53        6

output

  1       2       3       4       5        6
        2       3       4       5        6
      4       3324       4       53        6
    
por 04.12.2014 / 09:47
0

Sei que não resolvi usar sed ou awk ou nenhum dos comandos shell , mas tcl funcionou bem.

Mantive o script simples e amigável. elementos como 4a abc etc serão atendidos

comando

script.tcl file

Script

#!/usr/bin/tclsh

if {$argv == ""} {
        puts "please enter the arguement"
        exit ;
}

set tar_fl [lindex $argv 0]
if {![file exists $tar_fl]} {
        puts "$tar_fl doesnot exist"
        exit ;
}

set flptr [open $tar_fl r]

while {[gets $flptr line] >=0 } {
        if {[llength $line] !=5} {continue ;}
        if {[llength $line ] == 5} {
                if {[lsearch -regexp  $line {[^0-9]}]> -1} {continue;}
                puts $line
        }

}

close $flptr

Saída

           10      2       12      1       13
1       2       3       4       5
    
por 10.12.2014 / 09:08

Tags