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 / 498857
Accepted
TheDudeAbides
TheDudeAbides
Asked: 2019-02-06 09:18:18 +0800 CST2019-02-06 09:18:18 +0800 CST 2019-02-06 09:18:18 +0800 CST

Como posso evitar que opções 'shopt' não suportadas causem erros no meu .bashrc?

  • 772

Eu trabalho em um ambiente relativamente heterogêneo onde posso estar executando diferentes versões do Bash em diferentes nós HPC, VMs ou minha estação de trabalho pessoal. Como coloquei meus scripts de login em um repositório Git, gostaria de usar o mesmo (ish) .bashrcem geral, sem muita bagunça do tipo "se este host, então...".

Eu gosto do comportamento padrão do Bash ≤ 4.1 que se expande cd $SOMEPATHao cd /the/actual/pathpressionar a Tabtecla. No Bash 4.2 e acima, você precisaria shopt -s direxpandreativar esse comportamento, e isso não ficou disponível até 4.2.29 . Este é apenas um exemplo; shoptoutra opção possivelmente relacionada complete_fullquote(embora eu não saiba exatamente o que ela faz) também pode ter alterado o comportamento padrão na v4.2.

No entanto, direxpandnão é reconhecido por versões anteriores do Bash e, se eu tentar shopt -s direxpandno meu .bashrc, isso resultará em uma mensagem de erro sendo impressa no console toda vez que eu efetuar login em um nó com um Bash mais antigo:

-bash: shopt: direxpand: invalid shell option name

O que eu gostaria de fazer é envolver uma condicional shop -s direxpandpara habilitar essa opção no Bash > 4.1 de maneira robusta, sem irritar as versões mais antigas do Bash ( ou seja , não apenas redirecionar a saída de erro para /dev/null).

bash shell-script
  • 3 3 respostas
  • 1548 Views

3 respostas

  • Voted
  1. Gilles 'SO- stop being evil'
    2019-02-06T09:44:07+08:002019-02-06T09:44:07+08:00

    Não vejo o que há de errado em redirecionar erros para arquivos /dev/null. Se você quiser que seu código seja robusto set -e, use o idioma comum … || true:

    shopt -s direxpand 2>/dev/null || true
    

    Se você quiser executar algum código de fallback se a opção não existir, use o status de retorno de shopt:

    if shopt -s direxpand 2>/dev/null; then
      … # the direxpand option exists
    else
      … # the direxpand option does not exist
    fi
    

    Mas se você realmente não gosta de redirecionar o erro, pode usar o mecanismo de conclusão para realizar a introspecção. Isso pressupõe que você não tenha máquinas antiquadas com bash ≤ 2.03 que não tenham conclusão programável.

    shopt_exists () {
      compgen -A shopt -X \!"$1" "$1" >/dev/null
    }
    if shopt_exists direxpand; then
      shopt -s direxpand
    fi
    

    Esse método evita a bifurcação, que é lenta em alguns ambientes, como o Cygwin. O mesmo acontece com o simples 2>/dev/null, não acho que você possa superar isso em desempenho.

    • 18
  2. Best Answer
    Luciano Andress Martini
    2019-02-06T09:23:31+08:002019-02-06T09:23:31+08:00

    Verifique se direxpandestá presente na saída de shopte habilite-o se estiver:

    shopt | grep -q '^direxpand\b' && shopt -s direxpand
    
    • 14
  3. TheDudeAbides
    2019-02-06T09:18:18+08:002019-02-06T09:18:18+08:00

    Quando você sabe com certeza que uma shoptopção específica está disponível em uma determinada versão principal/secundária/patch do Bash, você pode inspecionar a $BASH_VERSIONvariável ou os elementos da $BASH_VERSINFO[]matriz para habilitá-la condicionalmente.

    Aqui está um teste para Bash 4.2.29 ou superior, a versão em que direxpand foi introduzida pela primeira vez na série 4.2:

    if [[ $BASH_VERSION == 4.2.* && ${BASH_VERSINFO[2]} -ge 29 ]] ||
       [[ ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -ge 3 ]] ||
       [[ ${BASH_VERSINFO[0]} -ge 5 ]]; then
        shopt -s direxpand
    fi
    

    Editar: Para ser claro, esta é uma solução ridiculamente projetada para simplesmente ignorar uma mensagem de erro proveniente de seus scripts de login, mas eu queria documentá-la independentemente, para minha própria edificação.

    Observe as chaves em torno de , que são necessárias, e o uso de e , que fazem comparações léxicas inteiras em vez de (dependentes de localidade). Se não estiver entre aspas, o RHS do operador é tratado como padrões "extglob" dentro do Bash / condicionais, conforme observado aqui , o que faz uma comparação "começa com" mais estética do que um regex faria, IMO.${BASH_VERSINFO[index]}-eq-gt==[[]]

    A $BASH_VERSINFOmatriz contém todas as informações que você veria na saída de bash --version:

    bash --version | head -1
    # result:
    # GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
    
    declare -p BASH_VERSINFO
    # result:
    # declare -ar BASH_VERSINFO='([0]="4" [1]="3" [2]="48" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")'
    

    Quando não está claro na documentação shoptem que as versões do Bash foram suportadas ou mudaram seu comportamento, o método proposto por Luciano está correto:

    # note the '-q' so that the matched pattern isn't actually printed
    shopt | grep -q direxpand && shopt -s direxpand
    

    ...como é a solução proposta por Gilles de simplesmente ignorar o erro ( shopt -s direxpand 2>/dev/null), e talvez checar $?se for absolutamente necessário.

    Referências: 1 , 2 , 3
    Leitura relacionada: Set and Shopt - Why Two?

    • 6

relate perguntas

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

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

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

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