Eu tenho um arquivo de log que precisa ser analisado e analisado. O arquivo contém algo semelhante como abaixo:
Arquivo:
20141101 server contain dump
20141101 server contain nothing
{uekdmsam ikdas
jwdjamc ksadkek} ssfjddkc * kdlsdl
sddsfd jfkdfk
20141101 server contain dump
Com base no cenário acima, tenho que verificar se a linha inicial não contém data ou número que tenho que acrescentar à linha anterior.
Arquivo de saída:
20141101 server contain dump
20141101 server contain nothing {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdl sddsfd jfkdfk
20141101 server contain dump
text-processing
sed
awk
William R
fonte
fonte
-0
se for para registros delimitados por NUL. Use-0777
para armazenar o arquivo inteiro na memória (o que você não precisa aqui).Pode ser um pouco fácil com
sed
primeira parte
:1;N;$!b1
coletar todas as linhas no arquivo dividido por\n
em 1 linha longaa segunda parte tira o símbolo de nova linha se seguir o símbolo de não dígito com possíveis espaços entre eles.
Para evitar limitação de memória (especialmente para arquivos grandes), você pode usar:
Ou esqueça um
sed
roteiro difícil e lembre-se de que o ano começa em2
fonte
tr '\n' $'\a' | sed $'s/\a\a*\( *[^0-9]\)/\1/g' | tr $'\a' '\n'
mim mesmo.+
é\{1,\}
.[\n]
também não é portátil.\n\{1,\}
seria POSIX.: 1;x
é definir o1;x
rótulo nos POSIX seds. Então, você precisa:sed -e :1 -e 'N;$!b1' -e 's/\n\{1,\}\( *[^0-9]\)/\1/g'
. Observe também que muitassed
implementações têm um pequeno limite no tamanho de seu espaço padrão (o POSIX garante apenas 10 x LINE_MAX IIRC).Uma maneira seria:
No entanto, também remove a nova linha final. Para adicioná-lo novamente, use:
Explicação
O
-l
removerá as novas linhas à direita (e também adicionará uma a cadaprint
chamada, motivo pelo qual eu uso issoprintf
. Em seguida, se a linha atual começar com números (/^\d+/
) e o número da linha atual for maior que um ($.>1
isso é necessário para evitar adicionar mais linha vazia no início), adicione\n
a ao início da linha eprintf
imprime cada linha.Como alternativa, você pode alterar todos os
\n
caracteres para e\0
, em seguida, alterar os\0
que estão corretos antes de uma sequência de números para\n
novamente:Para fazer corresponder apenas cadeias de 8 números, use este:
fonte
printf
é o formato . Useprintf "%s", $_
%10000000000s
por exemplo.perl
,echo %.10000000000f | perl -ne printf
traz minha máquina de joelhos.Tente fazer isso usando o awk :
Para usá-lo:
fonte
Outra maneira mais simples (do que a minha outra resposta) usando o algoritmo awk e terdon :
fonte
END{print ""}
. Alternativa:awk -v ORS= 'NR>1 && /^[0-9]{8}/{print "\n"};1;END{print "\n"}'
fonte
O programa no bash:
no formato de uma linha:
Solução com preservação de barras invertidas (
read -r
) e espaços à esquerda (logoIFS=
apóswhile
):formulário de uma linha:
fonte
n
. Ele também remove os espaços em branco. Mas você pode usarmksh
para fazer isso:while IFS= read -r L; do [[ $L = [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]* ]] && print; print -nr -- "$L"; done; print
isso vai funcionar
fonte