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 / 422348
Accepted
Lukali
Lukali
Asked: 2018-02-07 09:44:54 +0800 CST2018-02-07 09:44:54 +0800 CST 2018-02-07 09:44:54 +0800 CST

Como usar grep para procurar uma linha com uma de duas palavras, mas não ambas? [duplicado]

  • 772
Esta pergunta já tem respostas aqui :
Como faço grep para linhas contendo uma das duas palavras, mas não ambas? (6 respostas)
Fechado no ano passado .

Desejo procurar linhas com 'palavra1' XOR 'palavra2' em um arquivo de texto. Portanto, ele deve produzir linhas com palavra1, palavra2, mas não as linhas com essas duas palavras. Eu queria usar o XOR, mas não sei como escrever isso na linha de comando do Linux.

Eu tentei:

grep 'word1\|word2' text.txt
grep word1 word2 text.txt
grep word1 text.txt | grep word2
grep 'word1\^word2' text.txt

e muitos mais, mas não conseguiu obter sucesso.

grep text-processing
  • 3 3 respostas
  • 11410 Views

3 respostas

  • Voted
  1. Stéphane Chazelas
    2018-02-07T09:48:57+08:002018-02-07T09:48:57+08:00

    Com GNU awk:

    $ printf '%s\n' {foo,bar}{bar,foo} neither | gawk 'xor(/foo/,/bar/)'
    foofoo
    barbar
    

    Ou portabilidade:

    awk '((/foo/) + (/bar/)) % 2'
    

    Com um grepcom suporte para -P(PCRE):

    grep -P '^((?=.*foo)(?!.*bar)|(?=.*bar)(?!.*foo))'
    

    Com sed:

    sed '
      /foo/{
        /bar/d
        b
      }
      /bar/!d'
    

    Se você quiser considerar apenas palavras inteiras (que não há foonem barem foobarou barbarpor exemplo), você precisa decidir como essas palavras são delimitadas. Se for por qualquer caractere diferente de letras, dígitos e sublinhado, como a -wopção de muitas grepimplementações, você os alteraria para:

    gawk 'xor(/\<foo\>/,/\<bar\>/)'
    awk '((/(^|[^[:alnum:]_)foo([^[:alnum:]_]|$)/) + \
          (/(^|[^[:alnum:]_)bar([^[:alnum:]_]|$)/)) % 2'
    grep -P '^((?=.*\bfoo\b)(?!.*\bbar\b)|(?=.*\bbar\b)(?!.*\bfoo\b))'
    

    Pois sedisso se torna um pouco complicado, a menos que você tenha uma sedimplementação como o GNU sed que suporte \</ \>como limites de palavras como o GNU awk.

    • 17
  2. Best Answer
    Gilles 'SO- stop being evil'
    2018-02-07T13:23:29+08:002018-02-07T13:23:29+08:00

    grep 'word1\|word2' text.txtprocura por linhas contendo word1ou word2. Isso inclui linhas que contêm ambos.

    grep word1 text.txt | grep word2procura por linhas contendo word1e word2. As duas palavras podem se sobrepor (por exemplo , foobarcontém fooe ob). Outra maneira de pesquisar linhas contendo ambas as palavras, mas apenas de maneira não sobreposta, é procurá-las em qualquer ordem:grep 'word1.*word2\|word2.*word1' text.txt

    grep word1 text.txt | grep -v word2procura por linhas contendo, word1mas não word2. A -vopção diz ao grep para manter as linhas não correspondentes e remover as linhas correspondentes, em vez do contrário. Isso lhe dá metade dos resultados que você queria. Ao adicionar a pesquisa simétrica, você obtém todas as linhas que contêm exatamente uma das palavras.

    grep word1 text.txt | grep -v word2
    grep word2 text.txt | grep -v word1
    

    Como alternativa, você pode começar pelas linhas que contêm uma das palavras e remover as linhas que contêm as duas palavras. Dados os blocos de construção acima, isso é fácil se as palavras não se sobrepõem.

    grep 'word1\|word2' text.txt | grep -v 'word1.*word2\|word2.*word1'
    
    • 9
  3. user232326
    2018-02-07T14:08:06+08:002018-02-07T14:08:06+08:00

    Uma solução bash:

    #!/bin/bash 
    while (( $# )); do
        a=0 ; [[ $1 =~ foo ]] && a=1 
        b=0 ; [[ $1 =~ bar ]] && b=1
        (( a ^ b )) && echo "$1"
        shift
    done
    

    Para testar:

    $ ./script {foo,bar}\ {foo,bar} neither
    foo foo
    bar bar
    
    • 2

relate perguntas

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

  • Reorganize as letras e compare duas palavras

  • Subtraindo a mesma coluna entre duas linhas no awk

  • Embaralhamento de arquivo de várias linhas

  • como posso alterar o caso do caractere (de baixo para cima e vice-versa)? ao mesmo tempo [duplicado]

Sidebar

Stats

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

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

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 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

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 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
    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
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +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
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +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