Como anexar linha à linha anterior?

9

Eu tenho um arquivo de log que precisa ser analisado e analisado. 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, preciso verificar se a linha de partida não contém data ou o número que preciso anexar à 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
    
por William R 13.11.2014 / 18:08

8 respostas

11

Uma versão em perl , usando lookaheads negativos:

$ perl -0pe 's/\n(?!([0-9]{8}|$))//g' test.txt
20141101 server contain dump
20141101 server contain nothing    {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk
20141101 server contain dump

-0 permite que a regex seja correspondida em o arquivo inteiro , e \n(?!([0-9]{8}|$)) é um lookahead negativo, significando uma nova linha não seguida de 8 dígitos, ou o fim da linha (que, com -0 , será o final do arquivo). / p>     

por 13.11.2014 / 19:08
5

Um caminho seria:

 $ perl -lne 's/^/\n/ if $.>1 && /^\d+/; printf "%s",$_' file
 20141101 server contain dump
 20141101 server contain nothing    {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk 
 20141101 server contain dump

No entanto, isso também remove a nova linha final. Para adicioná-lo novamente, use:

$ { perl -lne 's/^/\n/ if $.>1 && /^\d+/; printf "%s",$_' file; echo; } > new

Explicação

O -l removerá as novas linhas finais (e também adicionará uma a cada print de chamadas, motivo pelo qual eu uso printf . Então, se a linha atual começar com números ( /^\d+/ ) e a linha atual number é maior que um ( $.>1 , isso é necessário para evitar adicionar uma linha extra vazia no início), adicione um \n ao início da linha. O printf imprime cada linha.

Como alternativa, você pode alterar todos os caracteres \n para \n e, em seguida, alterar os %code% que estão à direita antes de uma sequência de números para %code% novamente:

$ tr '\n' '
$ tr '\n' '
 $ perl -lne 's/^/\n/ if $.>1 && /^\d+/; printf "%s",$_' file
 20141101 server contain dump
 20141101 server contain nothing    {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk 
 20141101 server contain dump
' < file | perl -pe 's/
$ { perl -lne 's/^/\n/ if $.>1 && /^\d+/; printf "%s",$_' file; echo; } > new
\d{8} |$/\n$&/g' | tr -d '
$ tr '\n' '
$ tr '\n' '%pre%' < file | perl -pe 's/%pre%\d{8} |$/\n$&/g' | tr -d '%pre%'
' < file | perl -pe 's/%pre%\d+ |$/\n$&/g' | tr -d '%pre%' 20141101 server contain dump 20141101 server contain nothing {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk 20141101 server contain dump
'
' < file | perl -pe 's/%pre%\d+ |$/\n$&/g' | tr -d '%pre%' 20141101 server contain dump 20141101 server contain nothing {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk 20141101 server contain dump

Para fazer com que corresponda apenas a strings de 8 números, use isto:

%pre%     
por 13.11.2014 / 19:08
4

Pode ser um pouco fácil com sed

sed -e ':1 ; N ; $!b1' -e 's/\n\+\( *[^0-9]\)//g'
  • primeira parte :1;N;$!b1 coleta todas as linhas no arquivo divididas por \n em 1 linha longa

  • símbolo da nova linha da tira da segunda peça se seguir o símbolo não dígito com espaços possíveis entre o seu.

Para evitar limitação de memória (especialmente para arquivos grandes), você pode usar:

sed -e '1{h;d}' -e '1!{/^[0-9]/!{H;d};/^[0-9]/x;$G}' -e 's/\n\+\( *[^0-9]\)//g'

Ou esqueça os scripts sed difíceis e lembre-se de que o ano começa em 2

tr '\n2' ' \n' | sed -e '1!s/^/2/' -e 1{/^$/d} -e $a
    
por 13.11.2014 / 19:07
3

Tente fazer isso usando :

#!/usr/bin/awk -f

{
    # if the current line begins with 8 digits followed by
    # 'nothing' OR the current line doesn't start with 8 digits
    if (/^[0-9]{8}.*nothing/ || !/^[0-9]{8}/) {
        # print current line without newline
        printf "%s", $0
        # feeding a 'state' variable
        weird=1
    }
    else {
        # if last line was treated in the 'if' statement
        if (weird==1) {
            printf "\n%s", $0
            weird=0
        }
        else {
            print # print the current line
        }
    }
}
END{
    print # add a newline when there's no more line to treat
}

Para usá-lo:

chmod +x script.awk
./script.awk file.txt
    
por 13.11.2014 / 18:54
2

Outra maneira mais simples (que a minha outra resposta) é usar e < um algoritmo do href="https://unix.stackexchange.com/users/22222/terdon"> terdon :

awk 'NR>1 && /^[0-9]{8}/{printf "%s","\n"$0;next}{printf "%s",$0}END{print}' file
    
por 13.11.2014 / 19:47
1
sed -e:t -e '$!N;/\n *[0-9]{6}/!s/\n */ /;tt' -eP\;D
    
por 10.12.2016 / 15:13
0

Le programa en bash:

while read LINE
do
    if [[ $LINE =~ ^[0-9]{8} ]]
    then
        echo -ne "\n${LINE} "
    else
        echo -n "${LINE} "
    fi
done < file.txt

no formulário de uma linha:

while read L; do if [[ $L =~ ^[0-9]{8} ]]; then echo -ne "\n${L} "; else echo -n "${L} "; fi done < file.txt

Solução com barras invertidas preservando ( read -r ) e espaços iniciais (apenas IFS= após while ):

while IFS= read -r LINE
do
    if [[ $LINE =~ ^[0-9]{8} ]]
    then
        echo
        echo -nE "\n${LINE} "
    else
        echo -nE "${LINE} "
    fi
done < file.txt

formulário de uma linha:

while IFS= read -r L; do if [[ $L =~ ^[0-9]{8} ]]; then echo; echo -nE "${L} "; else echo -nE "${L} "; fi done < file.text
    
por 14.11.2014 / 16:44
0
[shyam@localhost ~]$ perl -lne 's/^/\n/ if $.>1 && /^\d+/; printf "%s",$_' appendDateText.txt

que funcionará

i/p:
##06/12/2016 20:30 Test Test Test
##TestTest
##06/12/2019 20:30 abbs  abcbcb abcbc
##06/11/2016 20:30 test test
##i123312331233123312331233123312331233123312331233Test
## 06/12/2016 20:30 abc

o/p:
##06/12/2016 20:30 Test Test TestTestTest
##06/12/2019 20:30 abbs  abcbcb abcbc
##06/11/2016 20:30 test ##testi123312331233123312331233123312331233123312331233Test
06/12/2016 20:30 abc vi appendDateText.txt 
    
por 05.10.2017 / 14:26