linux & solaris - IP's de máscara de rede separados de IP's comuns

2

Eu tenho um arquivo com endereço IP e IP de máscara de rede

minha meta é cortar os IPs da máscara de rede do arquivo file_with_IPs.txt e colá-los em outro arquivo como file_with_only_netmask_ips.txt

note - netmask IP pode ser qualquer combinação de máscara de rede IP, e pode começar por exemplo de xxx.xxx.xxx.xxx/1 até xxx.xxx.xxx.xxx/32

por exemplo

  10.140.4.11    10.140.4.110    
  255.255.0.0    255.255.255.0    
  10.219.39.188  10.219.39.200
  10.219.39.189  10.219.39.145
  10.140.4.12    10.140.4.120
  10.219.39.138   10.219.39.140
  10.219.39.139   10.219.39.239
  255.0.0.0        255.255.0.0
  255.255.255.128    255.255.255.192

então finalmente terei no arquivo file_with_IPs.txt

  10.140.4.11    10.140.4.110    
  10.219.39.188  10.219.39.200
  10.219.39.189  10.219.39.145
  10.140.4.12    10.140.4.120
  10.219.39.138   10.219.39.140
  10.219.39.139   10.219.39.239

e em file_with_only_netmask_ips.txt terei apenas os IPs da netmask como segue:

  255.255.0.0    255.255.255.0
  255.0.0.0        255.255.0.0
  255.255.255.128    255.255.255.192

Por favor, qual é a melhor maneira de separar os IPs da netmask dos IPs comuns?

Eu preciso escrever o procedimento com o shell ksh e preciso executar esse processo em máquinas Linux e Solaris

observa perl um linear, sed e awk podem estar no script ksh

    
por yael 18.06.2013 / 21:44

2 respostas

0

Uma maneira com awk :

awk '{
    for(i=1;i<=NF;i++) {
        if($i~/^255/) {
            netmask[NR]=i>1?netmask[NR]"\t"$i:$i
        }
        else { 
            regular[NR]=i>1?regular[NR]"\t"$i:$i
        }
    }
}
END {
    for(i=1;i<=NR;i++) {
        if (regular[i]) {
            print regular[i] > "file_with_IPs.txt"
        }
        if (netmask[i]) {
            print netmask[i] > "file_with_only_netmask_ips.txt"
        }
    }
}' file

Teste:

$ ls
file

$ cat file
10.140.4.11    10.140.4.110    
255.255.0.0    255.255.255.0    
10.219.39.188  10.219.39.200
10.219.39.189  10.219.39.145
10.140.4.12    10.140.4.120
10.219.39.138   10.219.39.140
10.219.39.139   10.219.39.239
255.0.0.0        255.255.0.0
255.255.255.128    255.255.255.192

$ awk '{
>     for(i=1;i<=NF;i++) {
>         if($i~/^255/) {
>             netmask[NR]=i>1?netmask[NR]"\t"$i:$i
>         }
>         else { 
>             regular[NR]=i>1?regular[NR]"\t"$i:$i
>         }
>     }
> }
> END {
>     for(i=1;i<=NR;i++) {
>         if (regular[i]) {
>             print regular[i] > "file_with_IPs.txt"
>         }
>         if (netmask[i]) {
>             print netmask[i] > "file_with_only_netmask_ips.txt"
>         }
>     }
> }' file

$ ls
file  file_with_IPs.txt  file_with_only_netmask_ips.txt

$ cat file_with_IPs.txt 
10.140.4.11     10.140.4.110
10.219.39.188   10.219.39.200
10.219.39.189   10.219.39.145
10.140.4.12     10.140.4.120
10.219.39.138   10.219.39.140
10.219.39.139   10.219.39.239

$ cat file_with_only_netmask_ips.txt 
255.255.0.0     255.255.255.0
255.0.0.0       255.255.0.0
255.255.255.128 255.255.255.192
    
por 19.06.2013 / 20:43
1

Por "IPs de máscara de rede", você parece querer dizer coisas com todos os bits definidos agrupados à esquerda. Existem apenas 32 desses, de / 0 a / 32. Você poderia apenas listá-los, em uma declaração grep (ou, melhor, em um arquivo que você passa para grep -f ).

Essa abordagem é tediosa, mas fácil;

^0\.0\.0\.0$
^128\.0\.0\.0$
^192\.0\.0\.0$
^224\.0\.0\.0$
⋮

Como na verdade é um padrão binário que estamos procurando, você poderia convertê-lo de volta em um número e, em seguida, fazer alguns ajustes no bit para confirmar que ele corresponde ao padrão. Isso seria uma tarefa de programação real, não algo que você jogaria junto com o grep.

Embora você possa fazer algo próximo com bc. Aqui está como testar $ip :

(
    echo 'obase=2';
    echo "$ip" | sed -e 's/\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)\.\([0-9]\+\)/*(256^3)+*(256^2)+*256+/'
) bc | grep -q '^1*0*$' && echo yes || echo no

Se você dividi-lo, o eco diz bc para a saída em binário. Então, essa linha sed transforma um endereço IP em uma expressão, para calcular seu valor numérico. 255.255.255.0 se torna 255*(256^3)+255*(256^2)+255*256+0 . Então bc vê:

obase=2
255*(256^3)+255*(256^2)+255*256+0

Imprime 11111111111111111111111100000000 , que é então verificado para corresponder ao padrão ^1*0*$ com grep .

Se você tiver um utilitário para converter um IP em um número, isso removerá a maior parte da complexidade acima. Ainda será provavelmente mais lento que o grep com uma lista de padrões.

    
por 18.06.2013 / 22:19