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 / 668839
Accepted
afernandezody
afernandezody
Asked: 2021-09-14 07:39:44 +0800 CST2021-09-14 07:39:44 +0800 CST 2021-09-14 07:39:44 +0800 CST

Verificando o formato de data no bash

  • 772

Eu tenho as seguintes linhas em um script bash:

 while true; do
    DATE=date
    FORMAT="%Y%m%d"
    read -p "Enter start date (YYYYMMDD)  " STARTDATE
    if date=$(date -d "$STARTDATE" +'+%Y%m%d'); then
       start_date=`$DATE +$FORMAT -d $STARTDATE`
       echo $start_date
       break
    fi
    echo "Please use right format (YYYYMMDD)  "
 done

Isso funciona bem desde que a entrada seja de 8 números (por exemplo, aceita "20210901" e rejeita "20213131"). No entanto, quando a entrada está totalmente desativada (por exemplo, "a" ou "nonsense"), ela simplesmente leva a data de hoje. Como o código poderia ser modificado para uma verificação mais rigorosa do formato?

O código modificado lê:

 valid=0
 while true; do
    DATE=date
    FORMAT="%Y%m%d"
    read -p "Enter start date (YYYYMMDD)  " initialdate
    if date=$(date -d "$initialdate" +'+%Y%m%d'); then
       start_date=`$DATE +$FORMAT -d $initialdate`
       if [[ "$start_date" =~ ^[[0123456789]]{8}$ ]]
       then
         valid=1 
         echo "valid"; 
         echo $start_date
         break
       else
         echo "Invalid format" 
       fi
    fi
    echo "Please use right format (YYYYMMDD)  "
 done
bash shell-script
  • 3 3 respostas
  • 1853 Views

3 respostas

  • Voted
  1. AdminBee
    2021-09-14T07:59:30+08:002021-09-14T07:59:30+08:00

    Como você pode reduzir a tarefa a uma verificação adicional exigindo que a entrada consista em exatamente 8 dígitos e esteja usando o Bash, você pode aproveitar o operador de comparação de expressão regular:

    if [[ "$startdate" =~ ^[0123456789]{8}$ ]]; then echo "valid"; else echo "invalid"; fi
    

    Isso verificará se o conteúdo de está de $startdateacordo com uma expressão regular que consiste em exatamente oito dígitos.

    Você pode combinar isso da seguinte forma:

    valid=0
    while (( valid == 0 )); do
        valid=1
        IFS= read -r -p "Enter start date (YYYYMMDD): " startdate
    
        if [[ ! "$startdate" =~ ^[0123456789]{8}$ ]]; then valid=0;
        elif ! date -d "$startdate" +%Y%m%d > /dev/null 2>&1 ; then valid=0; fi
    
        if (( valid == 0 )); then printf "Invalid date entered\n"; fi
    done
    
    # < ... operations for valid date here ... >
    

    Como uma regra geral:

    • Recomenda-se usar shellcheck, também disponível como programa autônomo em muitas distribuições Linux, para verificar seus scripts de shell.
    • É desencorajado usar nomes de variáveis ​​em letras maiúsculas, a menos que você queira exportá-los como variáveis ​​de ambiente, para evitar sobrescrever configurações críticas, como $PATHpor acidente.
    • 3
  2. Best Answer
    Kusalananda
    2021-09-14T11:20:32+08:002021-09-14T11:20:32+08:00

    Uma maneira comum de fazer validação de entrada é usar um loop infinito que você interrompe assim que a entrada for validada.

    Nesse caso, "validado" significa que a string de entrada contém apenas oito dígitos e que o GNU datepode usar essa data como um argumento de opção para sua -dopção.

    Com bash, poderíamos escrever isso como

    while true; do
        read -r -p 'Input date: '
    
        if [[ $REPLY =~ ^[[:digit:]]{8}$ ]] && date -d "$REPLY" >/dev/null 2>&1
        then
            break
        fi
    
        echo 'Invalid format, try again' >&2
    done
    
    thedate=$REPLY
    

    Isso lê a data no início do nosso loop e, em seguida, testa-a com uma expressão regular que corresponderá se a string contiver apenas oito dígitos. Se esse teste passar, a string também será testada com GNU date. Se tudo correr bem, o loop é encerrado por meio de uma breakinstrução.

    Em sh, precisamos substituir a correspondência de expressão regular por uma correspondência de padrão de shell:

    while true; do
        printf 'Input date: ' >&2
        read -r REPLY
    
        case $REPLY in
            *[![:digit:]]*)
                ;;
            ????????)
                date -d "$REPLY" >/dev/null 2>&1 && break
        esac
    
        echo 'Invalid format, try again' >&2
    done
    
    thedate=$REPLY
    

    O teste aqui primeiro testa se a string contém qualquer outro caractere além de um dígito. Se esse teste falhar, o próximo teste será para exatamente oito caracteres. Se esse teste for bem-sucedido, temos uma string de oito dígitos e testamos com GNU datee saímos do loop se a data estiver correta.

    • 3
  3. Jim L.
    2021-09-14T12:31:35+08:002021-09-14T12:31:35+08:00

    Ou sem o loop infinito, e assumindo o date(1)comando do BSD:

    REPLY=
    valid=false
    
    while ! $valid; do
    
        read -r -p 'Input date: '
    
        if ([[ $REPLY =~ ^[[:digit:]]{8}$ ]]) && (date -j +%Y%m%d ${REPLY}0000 >/dev/null 2>&1)
        then
            valid=true
        else
            echo 'Invalid format, try again' >&2
        fi
    
    done
    
    thedate=$REPLY
    

    A ${REPLY}0000sintaxe é necessária porque o BSD datedeseja um YmdHM completo, mas o padrão do HM 0000é suficiente.

    • 1

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