abordagem estranha:

abordagem estranha:

Eu tenho um arquivo com dados que salvo. Agora gostaria de imprimir meus resultados em um novo arquivo.

Por exemplo, vamos pegar este exemplo randomlog.log:

Link encap:Ethernet HWaddr 08:00:00:00:00:67
inet addr:10.10.10.10 Bcast:10.10.10.10 Mask:255.255.255.0
inet6 addr: fe80::casf:sdfg:23ra:dg12/64 Scope:Link

Como posso pegar apenas dados do 12º ao 20º caractere da primeira linha e depois do 4º ao 8º caracteres da 3ª linha? A saída seria algo assim:

Ethernet
t6 ad

Isso é possível? Quero definir a linha e da posição para esta posição.

Responder1

Aqui está uma sedabordagem:

$ sed -nE '1s/.{11}(.{8}).*/\1/p; 3s/.{3}(.{4}).*/\1/p' file  
Ethernet
t6 a

Explicação

O -nsuprime a saída normal (o normal é imprimir todas as linhas de entrada) para que ela seja impressa apenas quando solicitado. O -Epermite expressões regulares estendidas.

O sedscript possui dois comandos, ambos utilizando o operador de substituição ( s/original/replacement/). O 1s/.{11}(.{8}).*/\1/pserá executado apenas na primeira linha (é isso que 1sfaz) e corresponderá aos primeiros 11 caracteres da linha ( .{11}), entãocapturaos próximos 8 ( (.{8}), os parênteses são um "grupo de captura") e depois todo o resto até o final da linha ( .*). Tudo isso é substituído pelo que estava no grupo de captura ( \1; se houvesse um segundo grupo de captura, seria \2etc.). Por fim, o pno final ( s/foo/bar/p) faz com que a linha seja impressa após a substituição ter sido feita. Isso resulta na saída de apenas 8 caracteres de destino.

O segundo comando tem a mesma ideia geral, exceto que só será executado na 3ª linha ( 3s) e manterá os 4 caracteres a partir da 4ª.


Você também pode fazer a mesma coisa com perl:

$ perl -ne 'if($.==1){s/.{11}(.{8}).*/\1/}
            elsif($.==3){s/.{3}(.{4}).*/\1/}
            else{next}; print; ' file 
Ethernet
t6 a

Explicação

Os -nemeios "ler o arquivo de entrada linha por linha e aplicar o script fornecido por -ea cada linha. O script é a mesma ideia básica de antes. A $.variável contém o número da linha atual, então verificamos se o número da linha é ou 1e 3, se então, execute a substituição, caso contrário, pule. Portanto, printsó será executado para essas duas linhas, pois todas as outras serão ignoradas.


Claro, este é Perl, entãoTIMTOWTDI:

$ perl -F"" -lane '$. == 1 && print @F[11..19]; $.==3 && print @F[3..6]' file 
Ethernet 
t6 a

Explicação

Aqui, -asignifica "dividir cada linha de entrada no caractere fornecido por -Fe salvar como a matriz @F. Como o caractere fornecido está vazio, isso salvará cada caractere da linha de entrada como um elemento em @F. Em seguida, imprimimos os elementos 11-19 ( matrizes começam a contar em 0) para a 1ª linha e 3-7 para a 3ª.

Responder2

abordagem estranha:

$ awk 'NR==1{print substr($0,12,8)};NR==3{print substr($0,4,4)}' input.txt  
Ethernet
t6 a

Usa NRpara determinar o número da linha (na terminologia awk - registro) e, consequentemente, imprimir a substring da linha. substr()a função está no formato

substr(string,starting position,how much offset) 

Pitão

$ python -c 'import sys                                                                                                                                                
> for index,line in enumerate(sys.stdin,1):                                                                                                                            
>     if index == 1:
>          print line[11:19]
>     if index == 3:
>          print line[3:7]' < input.txt
Ethernet
t6 a

Isso usa <o operador shell para redirecionar o fluxo de entrada para o processo python do arquivo de entrada. Observe que as strings em python são indexadas em 0, portanto, você precisa mudar todos os números de caracteres desejados em 1.

maneira de concha portátil

Isso funciona em ksh, dash, bash. Depende apenas de utilitários shell, nada externo.

#!/bin/sh

rsubstr(){
    i=0;
    while [ $i -lt  $2 ];
    do
        rmcount="${rmcount}?"
        i=$(($i+1))
    done;
    echo "${1#$rmcount}"
}

lsubstr(){
    printf "%.${2}s\n" "$1"
}

line_handler(){
    case $2 in
        1) lsubstr "$(rsubstr "$1" 11)" 8 ;;
        3) lsubstr "$(rsubstr "$1" 3)" 5 ;;
    esac
}

readlines(){
    line_count=1
    while IFS= read -r line;
    do
        line_handler "$line" "$line_count"
        line_count=$(($line_count+1))
    done < $1
}

readlines "$1"

E funciona assim:

$ ./get_line_substrings.sh input.txt                                                                                                                                   
Ethernet
t6 ad

informação relacionada