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 / 443469
Accepted
jesse_b
jesse_b
Asked: 2018-05-13 13:58:45 +0800 CST2018-05-13 13:58:45 +0800 CST 2018-05-13 13:58:45 +0800 CST

Por que esse código funciona no bash v4.4, mas não no bash v3.2?

  • 772

Eu tenho o seguinte script bash:

#!/bin/bash

encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 0,10 0,11 0,12 0,13 0,14 0,15 )
MISSING_DISKS=()
OLDIFS=$IFS
IFS=$'\n'
MISSING_DISKS+=($({ printf '0 %s\n' {0..15}; printf '0 %s\n' "${encl0[@]#0,}"; } | sort | uniq -u))
IFS=$OLDIFS
echo "$({ printf '0 %s\n' {0..15}; printf '0 %s\n' "${encl0[@]#0,}"; } | sort | uniq -u)"
echo "${MISSING_DISKS[@]}"
if ((${#MISSING_DISKS[@]}>1)); then
    echo "Greater than 1"
else
    echo "Success"
fi

Quando o executo com o bash v4.4, funciona como esperado:

$ /usr/local/bin/bash test.sh
0 6
0 6
Success

No entanto, quando eu o executo com o bash v3.2, ele não:

$ /bin/bash test.sh
0 6
0 0 0 0 1 2 3 4 5 7 8 9 10 11 12 13 14 15 0 1 0 10 0 11 0 12 0 13 0 14 0 15 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9
Greater than 1

Não entendo como MISSING_DISKSestá sendo definido para algo diferente da saída do comando que o está configurando. Alguém sabe o que está causando isso?

bash shell-script
  • 1 1 respostas
  • 271 Views

1 respostas

  • Voted
  1. Best Answer
    user232326
    2018-05-13T18:55:10+08:002018-05-13T18:55:10+08:00

    Brincar com espaços, tabulações ou novas linhas está sempre perto do fracasso.

    O problema central ocorre aqui:

    encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 )
    IFS=$'\n'
    printf '<0 %s>\n' "${encl0[@]#0,}"
    

    Se executado no bash 3.2:

    $ b32sh ./script
    <0 0 1 2 3 4 5 7 8 9>
    

    A expansão de "${encl0[@]#0,}"é processada como uma string, não uma lista de valores.

    O problema não se manifesta se o IFS tiver um espaço ou se a expansão não editar cada valor do array:

    #!/bin/bash
    encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 )
    IFS=$' \n'
    printf '<0 %s>\n' "${encl0[@]#0,}"
    

    Executado:

    $ b32sh ./script
    <0 0>
    <0 1>
    <0 2>
    <0 3>
    <0 4>
    <0 5>
    <0 7>
    <0 8>
    <0 9>
    

    Ou:

    #!/bin/bash
    encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 )
    IFS=$'\n'
    printf '<0 %s>\n' "${encl0[@]}"
    

    Executado:

    b32sh ./so
    <0 0,0>
    <0 0,1>
    <0 0,2>
    <0 0,3>
    <0 0,4>
    <0 0,5>
    <0 0,7>
    <0 0,8>
    <0 0,9>
    

    O problema está oculto em seu script porque você restaura o IFS IFS=$OLDIFS antes da linha de eco de teste.

    Uma maneira de evitar o problema é não usar um espaço no printf:

    #!/bin/bash
    encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 0,10 0,11 0,12 0,13 0,14 0,15 )
    MISSING_DISKS=()
    OLDIFS=$IFS
    IFS=$' \n'
    MISSING_DISKS+=($({ printf '0x%s\n' {0..15}; printf '0x%s\n' "${encl0[@]#0,}"; } | sort | uniq -u))
    echo "test $({ printf '0x%s\n' {0..15}; printf '0x%s\n' "${encl0[@]#0,}"; } | sort | uniq -u)"
    echo "var  ${MISSING_DISKS[@]}"
    if ((${#MISSING_DISKS[@]}>1)); then
        echo "Greater than 1"
    else
        echo "Success"
    fi
    IFS=$OLDIFS
    

    A outra alternativa é evitar a expansão com substituição após alterar o IFS para uma nova linha usando um array alternativo:

    #!/bin/bash
    OLDIFS=$IFS
    encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 0,10 0,11 0,12 0,13 0,14 0,15 )
    IFS=$' \n'; arr=("${encl0[@]#0,}")
    MISSING_DISKS=()
    IFS=$'\n'
    MISSING_DISKS+=($({ printf '0 %s\n' {0..15}; printf '0 %s\n' "${arr[@]}"; } | sort | uniq -u))
    echo "test $({ printf '0 %s\n' {0..15}; printf '0 %s\n' "${arr[@]}"; } | sort | uniq -u)"
    echo "var  ${MISSING_DISKS[@]}"
    if ((${#MISSING_DISKS[@]}>1)); then
        echo "Greater than 1"
    else
        echo "Success"
    fi
    IFS=$OLDIFS
    

    Eu te recomendo que:

    • Siga a regra de que variáveis ​​em CAPS são variáveis ​​de ambiente.
    • Não há necessidade de aumentar +=uma matriz que esteja vazia nesse ponto do código MISSING_DISKS+=.
    • Use um caractere sem espaço no printf para evitar a necessidade de remover o espaço do último IFS. Isso torna o script mais robusto.

    Se essas alterações forem feitas, o script se tornará:

    #!/bin/bash
    oldIFS=$IFS
    encl0=( 0,0 0,1 0,2 0,3 0,4 0,5 0,7 0,8 0,9 0,10 0,11 0,12 0,13 0,14 0,15 )
    unset missing_disks
    
    IFS=' '
               arr=($(printf '0-%s\n' "${encl0[@]#0,}"))
               arr+=($(printf '0-%s\n' {0..15}))
    
    missing_disks=($(printf '%s\n' "${arr[@]}" | sort | uniq -u))
    
               echo "test $(printf '0-%s\n' "${arr[@]}" | sort | uniq -u)"
               echo "var  ${missing_disks[@]}"
    
    ((${#missing_disks[@]}>1)) && echo "Greater than 1" || echo "Success"
    IFS=$oldIFS
    
    • 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

    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