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 / 769486
Accepted
Seamus
Seamus
Asked: 2024-02-17 09:44:37 +0800 CST2024-02-17 09:44:37 +0800 CST 2024-02-17 09:44:37 +0800 CST

Por que o grep ignora o '.' inicial?

  • 772

Estou tentando encontrar uma string em uma página da web baixada com curl. Estou usando greppara encontrar a string que corresponde a um padrão de expressão regular .

A seguir está a string que estou tentando encontrar:

./download/file.php?id=86753

Esta string faz parte desta string maior na página da web:

href="./download/file.php?id=86753"

O grepencantamento com o qual estou trabalhando é o seguinte:

grep -Eo '\.\/download\/file\.php\?id=[0-9]+' dlfile.html

Mas isso não encontra nada no arquivo html. No entanto, se eu modificar grepda seguinte forma, recebo duas (2) correspondências. A primeira partida é a que preciso; a segunda é uma distração inútil e não deve ser incluída:

grep -Eo '\/download\/file\.php\?id=[0-9]+' dlfile.html
/download/file.php?id=86753
/download/file.php?id=62517

A string que contém a segunda correspondência (indesejada) é a seguinte:

href="https://web.archive.org/web/20190824162104/https://www.somewhere.com/forums/download/file.php?id=62517&sid=907ab04af81e19ad758c5bcf8ebdca32"

Parece que o problema é a falha em reconhecer o início .(ponto) na string. Observe que esta é a principal diferença entre a string desejada e a string indesejada.

P: Por que isso não funciona e o que eu preciso?


Meu ambiente: derivado do Debian (Raspberry Pi), versão 'bullseye'

Qual grepe bashestou usando?

$ grep --version
grep (GNU grep) 3.6
...
$ bash --version
GNU bash, version 5.1.4(1)-release (arm-unknown-linux-gnueabihf)
grep
  • 4 4 respostas
  • 157 Views

4 respostas

  • Voted
  1. Chris Davies
    2024-02-17T17:06:05+08:002024-02-17T17:06:05+08:00

    Você usou grep -E, exigindo Expressões Regulares Estendidas (EREs). Dot sempre deve ser escapado como literal. O ponto de interrogação é um operador válido para EREs, portanto, para corresponder como literal, ele também deve ter escape:

    echo 'href="./download/file.php?id=86753"' |
        grep -Eo '\./download/file.php\?id=[0-9]+'
    

    Você perguntou,

    Por que o grep ignora o '.' inicial?

    Parece que o problema é a falha em reconhecer o líder. (ponto) na string.

    Seu padrão corresponde e requer um ponto literal (é isso que \.significa). No entanto, a string que você descreveu na sua pergunta não aparece na página da web que você está tentando pesquisar. grepnão ignora isso; isso exige. Olhar:

    xmlstarlet format --html BDegguyM 2>/dev/null |
        xmlstarlet select -T -t -v '//a[@class="postlink"]/@href' -n
    
      https://forums.raspberrypi.com/download/file.php?id=86753
      https://web.archive.org/web/20190824162104/https://www.raspberrypi.org/forums/download/file.php?id=62517&sid=907ab04af81e19ad758c5bcf8ebdca32
    

    Presumo que você queira o primeiro deles, então vamos extrair esse:

    xmlstarlet format --html BDegguyM 2>/dev/null |
        xmlstarlet select -T -t -v '//dl[@class="file"]//a[@class="postlink"]/@href' -n
    
      https://forums.raspberrypi.com/download/file.php?id=86753
    

    Se você quiser apenas a parte começando, /downloadvocê pode retirá-la facilmente

    xmlstarlet format --html BDegguyM 2>/dev/null |
        xmlstarlet select -T -t -v '//dl[@class="file"]//a[@class="postlink"]/@href' -n |
        sed -E 's!^https?://[^/]+!!'
    
      /download/file.php?id=86753
    

    Se você realmente deseja usar grepa ferramenta certa para o trabalho, isso retornará o mesmo resultado:

    grep -Po 'https?://[^/]+\K/download/file.php\?id=\d+' BDegguyM
    
      /download/file.php?id=86753
    
    • 0
  2. Ed Morton
    2024-02-19T08:08:42+08:002024-02-19T08:08:42+08:00

    A resposta à pergunta na sua linha de assunto:

    Por que o grep ignora o '.' inicial?

    é simplesmente - isso não acontece.

    Usando as duas linhas de entrada de amostra que você forneceu juntas em um arquivo:

    $ cat dlfile.html
    href="./download/file.php?id=86753"
    href="https://web.archive.org/web/20190824162104/https://www.somewhere.com/forums/download/file.php?id=62517&sid=907ab04af81e19ad758c5bcf8ebdca32"
    

    e apenas removendo as barras invertidas indesejáveis ​​(provavelmente inofensivas, mas definitivamente dependendo do comportamento indefinido por POSIX) antes do /s e executando os 2 grepcomandos em sua pergunta:

    $ grep -Eo '\./download/file\.php\?id=[0-9]+' dlfile.html
    ./download/file.php?id=86753
    
    $ grep -Eo '/download/file\.php\?id=[0-9]+' dlfile.html
    /download/file.php?id=86753
    /download/file.php?id=62517
    

    O primeiro grep, que inclui um início ., corresponde apenas à string da entrada que tem um início, .enquanto o segundo grep, que não inclui um início ., sem surpresa corresponde a 2 strings da entrada que não começam com um ..

    Em relação ao seu comentário sobre o primeiro grepacima:

    Mas isso não encontra nada no arquivo html.

    qualquer então:

    1. O comando grep na sua pergunta não é o mesmo que você está usando ou
    2. O arquivo HTML real não contém as strings que você forneceu para usarmos como amostra de entrada

    portanto, não há realmente nada que possamos fazer para ajudá-lo a depurar um comando que você está usando para analisar alguma entrada quando não sabemos a aparência do seu comando ou não sabemos como é a sua entrada.

    • 0
  3. Best Answer
    Seamus
    2024-02-20T02:55:26+08:002024-02-20T02:55:26+08:00

    Houve muitos comentários aqui. Alguns deles levantaram preocupações e questões válidas. Acredito que finalmente resolvi o problema e estou postando isso aqui em um esforço para encerrar.

    Como você deve ter percebido, eu estava "raspando" uma URL em busca de uma string contendo um item de informação que eu precisava. Desenvolvi um script para "automatizar" essa tarefa, talvez há 2 anos, e funcionou perfeitamente. O script faz duas coisas principais:

    1. curle grepa página da web
    2. tomar outras medidas com base no grepresultado

    "Algo mudou" há alguns dias. Meu script "confiável" começou a gerar um erro durante cada execução; a indicação de erro sugeria que grepnão estava conseguindo encontrar a string. O que grepeu estava usando:

    curl blah-blah | grep -o '\.\/download\/file\.php?id.[0-9]*'
    

    Até agora, ainda não sei tudo o que mudou. Acredito que uma das mudanças é que o site foi terceirizado para uma empresa chamada “CloudFlare”; outra parece ser que eles não lidam mais com curldownloads da mesma forma que lidam com downloads de um navegador. Mudanças adicionais parecem estar ocorrendo.

    A confusão refletida na minha pergunta se deve em parte a essas alterações no site, mas se deve principalmente a mim . Eu deveria ter sido paciente e investigado o erro mais detalhadamente antes de postar uma pergunta. Minhas desculpas a todos os envolvidos.

    Uma coisa que afirmo ter aprendido com essa experiência: grepnão é a ferramenta correta para analisar HTML . Tenho duas referências para compartilhar:

    1. Este tópico polêmico do SO está usando regexes para analisar HTML

    2. Esta postagem informativa de Hiks Gerganov intitulada "Análise de HTML para extrair texto entre tags HTML no Shell".

    • 0
  4. Toby Speight
    2024-02-17T17:23:45+08:002024-02-17T17:23:45+08:00

    Funciona bem aqui se eu mudar \/para plain /:

    #!/usr/bin/sh
    
    printf 'href="%s"\n' \
           './download/file.php?id=86753' \
           'elsewhere/download/file.php?id=86753' |
        grep -oE '\./download/file\.php\?id=[0-9]+'
    

    Saída:

    ./download/file.php?id=86753
    

    Você também pode considerar adicionar \Bno início e \bno final para melhor rejeição de quase-acidentes indesejados.

    • -1

relate perguntas

  • resultados inesperados de `service | grep`

  • Leia o arquivo de texto com palavras e sua contagem de ocorrências e saída de impressão classificada

  • Comando ls | grep mostrando apenas diretórios (quando também deveria mostrar arquivos)

  • quando o grep conta e quando não

  • grep --line-buffered até X linhas?

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