Remove tudo o que não é um número de 4 caracteres

4

Eu preciso remover tudo o que não é um número de 4 caracteres, como 9838 , 6738 , 1337 ou 1889 .

Eu achei que esse comando funcionaria:

sed 's/....[^0-9]//g'

. Significa qualquer caractere na regex e [^0-9] não remove nenhum número.

Aqui está uma entrada de exemplo:

9228 Hello 8473 World War 1 1914-1918 Hello 8391 World War 2 1939-1945

Seria:

9228 8473 1914 1918 8391 1939 1945
    
por DisplayName 25.11.2014 / 16:27

8 respostas

8

Eu posso responder com o comando grep :

Arquivo de entrada:

9228 Hello 8473 World War 1 1914-1918 Hello 8391 World War 2 1939-1945

Comando:

grep -Eo '\<[0-9]{4}\>' file |tr '\n' ' '

Retorna qualquer número com tamanho = 4.

-E muda para regex estendido -o imprime apenas a parte correspondente

Saída:

9228 8473 1914 1918 8391 1939 1945

Atualizar resposta:

Arquivo de entrada:

9228 Hello 8473 World War 1 1914-1918 Hello 8391 World War 2 1939-1945

foo1234bar
a1111
12345
0x2222ff
1.3333
2.54321

Comando

grep -oP '(?<![0-9])[0-9]{4}(?![0-9])' file | tr '\n' ' '

grep com lookbehind negativo / lookahead:

(?<![0-9])[0-9]{4} (lookbehind negativo): corresponde a números com comprimento = 4 que não é precedido por um número [0-9] .
[0-9]{4}(?![0-9]) (lookahead negativo): corresponde a um número = 4 não seguido por um número .

Saída:

9228 8473 1914 1918 8391 1939 1945 1234 1111 2222 3333
    
por 25.11.2014 / 16:33
5

Você pode usar perl .

perl -nle'print join " ", /(?<![0-9])[0-9]{4}(?![0-9])/g'

Isso também funciona para entrada de várias linhas, portanto, se você tiver:

9228 Hello 8473 World War 1 1914-1918
Hello 8391 World War 2 1939-1945

Você receberá o seguinte:

9228 8473 1914 1918
8391 1939 1945

(Adicione -0777 se você quiser os números na mesma linha.)

    
por 25.11.2014 / 17:29
4

POSIXly:

< file tr -cs 0-9 '[\n*]' | grep -xE '.{4}' | paste  -sd ' ' -
    
por 25.11.2014 / 17:00
2

com perl :

$ perl -Tnle 'BEGIN {$, = " "} print $_ =~ /\b\d{4}\b/g' file
9228 8473 1914 1918 8391 1939 1945
    
por 25.11.2014 / 17:19
1

Com um único s/// , você pode fazer isso em um POSIX sed , mas há muitas barras invertidas:

sed 's/[^0-9]*\([0-9]\{5,\}\)*[^0-9]*\([0-9]\{4\}\)*.\{0,1\}/ /g
' <<\IN
92828 Hello 8473 World War 1 1914-1918 Hello 8391 World War 2 1939-1945
IN

OUTPUT

8473  1914 1918 8391  1939 1945

Ele g lobalmente engole todas as sequências com 5 ou mais dígitos primeiro - então qualquer ^ não digita - então sua correspondência e os últimos 0 ou 1 de qualquer outro caractere. Em toda essa declaração, apenas 1 expressão é salva - sua correspondência - e, portanto, isso é o que resta - além de quaisquer espaços em branco intervenientes.

Mas com um pouco de tradução, as coisas ficam mais fáceis:

sed 'y/ /./;s/[0-9]\{4,\}/ & /g;s/\( [^ ]\{4\} \)*[^ ]*//g
' <<\IN
92828 Hello 8473 World War 1 1914-1918 Hello 8391 World War 2 1939-1945
IN

OUTPUT

  8473  1914  1918  8391  1939  1945 

sed primeiro traduz todos os espaços para pontos. Em seguida, envolve qualquer seqüência de 4 ou mais dígitos em espaços. E por último, remove todos os caracteres não-espaciais, salvo qualquer sequência de quatro rodeada por espaços.

    
por 25.11.2014 / 18:38
0

com gawk

echo '9228 Hello 8473 World War 1 1914-1918 Hello 8391 World War 2 1939-1945' |
awk --re-interval -v RS='\y[[:digit:]]{4}\y' '{printf "%s ", RT}END{print ""}'
9228 8473 1914 1918 8391 1939 1945
    
por 25.11.2014 / 17:48
0

Python

Em python eu faria como o abaixo,

#!/usr/bin/python
import re
import sys
file = sys.argv[1]
with open(file, 'r') as f:
    for line in f:
        print ' '.join(re.findall(r'(?<!\d)\d{4}(?!\d)', line))

Salve o script acima como script.py e, em seguida, execute-o aplicando o comando abaixo no terminal.

python script.py file

Exemplo:

$ cat file
9228 Hello 8473 World War 1 1914-1918 Hello 8391 World War 2 1939-1945
foo1234bar 0x1234ff 1.1234
$ python f.py file
9228 8473 1914 1918 8391 1939 1945
1234 1234 1234

Perl

Através do comando s/// do perl. Esse é o comando de pesquisa e substituição.

perl -pe 's/(?<!\d)\d{4}(?!\d)(*SKIP)(*F)|.+?(?=\d{4}|$)/ /g;s/^ +| +$//g' file

Exemplo:

$ cat file
9228 Hello 8473 World War 1 1914-1918 Hello
foo1234bar 0x1234ff 1.1234
$ perl -pe 's/(?<!\d)\d{4}(?!\d)(*SKIP)(*F)|.+?(?=\d{4}|$)/ /g;s/^ +| +$//g' file
9228 8473 1914 1918
1234 1234 1234

Leia aqui para saber mais sobre o verbo PCRE (*SKIP)(*F) .

    
por 26.11.2014 / 07:00
0

Apenas no caso de precisar de outra versão da resposta com base em sed .

$ sed -re 's#(\b[0-9]{4}\b)*([^0-9]|\b[0-9]\b)*# #g' file.txt
9228 8473 1914 1918 8391 1939 1945 
    
por 28.11.2014 / 10:08