AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 790845
Accepted
Matt S.
Matt S.
Asked: 2025-02-10 20:41:16 +0800 CST2025-02-10 20:41:16 +0800 CST 2025-02-10 20:41:16 +0800 CST

Lista de ip em loop através do geoiplookup e apaga linhas que não correspondem aos critérios

  • 772

Agradecemos antecipadamente por qualquer ideia que você apresentar.

Meu projeto atual consiste em tentar fazer um loop de um arquivo contendo uma lista de milhares de endereços IP por meio do geoiplookup e direcioná-lo ao sed para excluir todas as linhas que não correspondem aos critérios.

A lista é apenas uma lista de endereços IP:

1.2.3.4
5.6.7.8
9.10.11.12
.
.
.

Em seguida, executo geoiplookup ip.ad.dre.sscomo root e obtenho:

[root@system ipset]# geoiplookup 4.2.2.2
GeoIP Country Edition: US, United States

se o IP estiver dentro dos EUA.

Meu objetivo é excluir todas as linhas do arquivo, se o IP deles não estiver nos EUA.

O que tentei não está funcionando:

#!/bin/bash

for ip in $(cat /tmp/iplist.txt); do
     geoiplookup $ip | sed '/GeoIP Country Edition: US, United States/!d'
done

Alguma sugestão? Recomendações de outra abordagem seriam muito apreciadas.

@terdon Desculpe não ter atualizado antes, estive ocupado.

Adicionar qualquer um a esta pergunta ou comentário bagunça a formatação do texto. Desculpe, novato no Stack...deixe-me descobrir isso.

OK, atualização.

depois de alterar e executar o primeiro código do @terdon:

#!/bin/bash

while read ip; do
  if ! geoiplookup "$ip" | grep -q ': US, United States$'; then
    sed -i "/^$ip$/d" /tmp/iplist.txt
  fi
done < /tmp/iplist.txt

ele roda sem erros, mas endereços IP não americanos ainda estão na lista.

Eu estava usando o último exemplo com odeclare -a badLines

scripts#geoiplookup 172.168.155.63
GeoIP Country Edition: GB, United Kingdom

scripts#grep 172.168.155.63 /tmp/iplist.txt
172.168.155.63

Assim que eu descobrir como fazer o copiar e colar funcionar corretamente na pergunta, atualizarei.

@Ed Morton Ambos os exemplos produzem o mesmo erro na linha "done", linha 7 em um e linha 9 no outro.

./filter_ips.sh: line 7: syntax error near unexpected token `done'
./filter_ips.sh: line 7: `   done < "${@:--}"'

@Miri B Eles funcionam, mas ainda há endereços IP de fora dos EUA na lista.

shell-script
  • 3 3 respostas
  • 53 Views

3 respostas

  • Voted
  1. Best Answer
    terdon
    2025-02-10T21:27:53+08:002025-02-10T21:27:53+08:00

    Você quer fazer um loop sobre as linhas, verificar se elas contêm um IP que mapeia para os EUA e, se não, excluir essa linha do arquivo. Sua abordagem falhou porque você está usando sedna saída do geoiplookupcomando, não no arquivo.

    O que você precisa fazer é verificar cada IP e, então, voltar ao arquivo. Então você pode fazer algo assim (note que não estou usando for i in $(cat file)aqui; veja Bash pitfall #1 para saber por que isso é uma má ideia):

    ## make a backup of your file
    cp ip.ad.dre.ss ip.ad.dre.ss.bak
    while read ip; do
       if ! geoiplookup "$ip" | grep -q ': US, United States$'; then
          sed -i "/^$ip$/d" ip.ad.dre.ss
       fi
    done < ip.ad.dre.ss
    

    Note que isso também removerá entradas que simplesmente não podem ser mapeadas para sua localização. Por exemplo, algo como este site:

    $ geoiplookup unix.stackexchange.com
    GeoIP Country Edition: IP Address not found
    

    Se você quiser mantê-los, você pode usar isto:

    while read ip; do    
        if ! geoiplookup "$ip" | 
          grep -Eq ': (US, United States|IP Address not found)$'; then
              sed -i "/^$ip$/d" ip.ad.dre.ss
        fi
    done < ip.ad.dre.ss
    

    No entanto, ambos são um pouco ineficientes, pois precisam que o arquivo inteiro seja processado várias vezes. Uma abordagem alternativa seria ler o arquivo uma vez para gerar a lista de linhas que você deseja excluir e, em seguida, excluí-las com uma segunda passagem. Algo assim:

    declare -a badLines
    while read ip; do
        ((c++))
    
        if ! geoiplookup "$ip" | 
          grep -Eq ': (US, United States|IP Address not found)$'; then
              badLines+=($c)
        fi
    done < ip.ad.dre.ss
    
    sedCommand=$(sed -E 's/ |$/d;/g' <<<"${badLines[@]}")
    sed -i "$sedCommand" ip.ad.dre.ss
    

    Se você passar sedo comando Ndonde Né um número, ele apagará o número da linha da entrada. Então, se eu executar sed 2d file, isso imprime o conteúdo do arquivo, exceto a segunda linha. Lembre-se, sempre com sed, se você quiser que a alteração seja realmente salva no arquivo , você precisa de -i. So sed -i 2d fileapagará a segunda linha de file.

    Aqui, estou lendo o arquivo uma vez e coletando a lista de números de linha que quero excluir. Então, eu converto essa lista separada por espaços, para o Nd;formato com um pequeno sedcomando e, finalmente, estou passando o comando sed resultante (pareceria com 2d;3d;130d;etc) para sedrealmente modificar o arquivo.

    • 0
  2. Ed Morton
    2025-02-10T22:53:17+08:002025-02-10T22:53:17+08:00

    Se geoiplookup(o que eu não tenho) só puder processar 1 endereço IP por vez, considere algo como o seguinte (não testado):

    #!/usr/bin/env bash
    
    getUsaIps() {
        local ip re='United States$'
        while IFS= read -r ip
            if [[ "$(geoiplookup "$ip")" =~ $re ]]; then
                printf '%s\n' "$ip"
            fi
        done < "${@:--}"
    }
    
    tmp="$(mktemp)" || exit
    trap 'rm -f "$tmp"; exit' EXIT
    
    infile='/tmp/iplist.txt'
    getUsaIps "$infile" > "$tmp" &&
    mv -- "$tmp" "$infile"
    

    ou:

    #!/usr/bin/env bash
    
    getIpMap() {
        local ip
        while IFS= read -r ip
            printf '%s\t%s\n' "$ip" "$(geoiplookup "$ip")"
        done < "${@:--}"
    }
    
    tmp="$(mktemp)" || exit
    trap 'rm -f "$tmp"; exit' EXIT
    
    infile='/tmp/iplist.txt'
    getIpMap "$infile" | awk '/United States$/{ print $1 }' > "$tmp" &&
    mv -- "$tmp" "$infile"
    
    • 0
  3. Miri B
    2025-02-12T03:54:29+08:002025-02-12T03:54:29+08:00

    Experimente estes dois códigos awk:

    awk '{ 
           cmd=("geoiplookup " $0); cmd | getline s ; 
           close(cmd); 
           if( s ~ /Country Edition: US, United States/ ) print  $0
         }'  file_name
    

    Ou outro, provavelmente mais rápido:

    awk '{ printf"%s ", $0; system("geoiplookup " $0) }'  file_name | 
       awk '/GeoIP Country Edition: US, United States/{print $1}'
    
    • 0

relate perguntas

  • Subtraindo a mesma coluna entre duas linhas no awk

  • Um script que imprime as linhas de um arquivo com seu comprimento [fechado]

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Dividir por delimitador e concatenar problema de string

  • MySQL Select com função IN () com array bash

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve