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 / 410961
Accepted
David Z
David Z
Asked: 2017-12-15 15:39:20 +0800 CST2017-12-15 15:39:20 +0800 CST 2017-12-15 15:39:20 +0800 CST

Gravando um comando em um arquivo de script com aspas apropriadas

  • 772

Uma situação com a qual me deparei algumas vezes: tenho uma função de shell que faz algumas configurações e depois invoca um comando mais ou menos arbitrário, como este:

setup_and_run() {
    some_setup_commands
    "$@"
}

Eu quero alterar esta função para também escrever um arquivo de script que eu possa usar para executar novamente o comando depois de fazer a mesma configuração. Posso fazer o seguinte, que funciona quando não há argumentos com espaços ou outras coisas estranhas no comando:

setup_and_run() {
    some_setup_commands
    cat >>rerun.sh <<EOF
some_setup_commands
$@
EOF
    "$@"
}

Existe uma maneira padrão de alterar isso para que o script seja escrito com aspas adequadas, em geral, mesmo que alguns argumentos tenham espaços ou outros caracteres especiais?

Por exemplo, com a segunda definição de setup_and_run, se eu executar

$ setup_and_run ls "my cat's \"password\""
my cat's "password"

então rerun.shconterá

some_setup_commands
ls my cat's "password"

Considerando que eu quero que contenha algo como

some_setup_commands
ls "my cat's \"password\""

ou

some_setup_commands
ls my\ cat\'s\ \"password\"

ou algo assim.

Em um piscar de olhos, posso terceirizar isso para algo como Python's shlex.quote(), mas estou procurando algo que possa ser feito no próprio shell, se possível, ou pelo menos usando uma ferramenta UNIX padrão mais leve.

bash shell-script
  • 1 1 respostas
  • 1131 Views

1 respostas

  • Voted
  1. Best Answer
    Gilles 'SO- stop being evil'
    2017-12-15T16:23:23+08:002017-12-15T16:23:23+08:00

    No bash, ksh93 e zsh, você pode usar o %qescape para o printfarquivo .

    #!/bin/bash
    # also works in ksh93, zsh
    setup_and_run() {
        some_setup_commands
        cat >>rerun.sh <<EOF
    some_setup_commands
    $(printf '%q ' "$@")
    EOF
        "$@"
    }
    

    No bash, você pode usar o printf -vpara gravar a saída em uma variável em vez de na saída padrão.

    #!/bin/bash
    printf -v cmd '%q ' "$@"
    setup_and_run() {
        some_setup_commands
        cat >>rerun.sh <<EOF
    some_setup_commands
    $cmd
    EOF
        "$@"
    }
    

    No zsh, há um método diferente que é o q sinalizador de expansão de parâmetro , seguido por j: :para unir os elementos da matriz com um espaço.

    #!/bin/zsh
    setup_and_run() {
        some_setup_commands
        cat >>rerun.sh <<EOF
    some_setup_commands
    ${(j: :)${(q)@}}
    EOF
        "$@"
    }
    

    Em sh simples, é mais difícil. Uma maneira confiável de citar uma palavra é colocá-la entre aspas simples e substituir cada aspa dentro dela por '\''. Fazer a substituição corretamente não é muito fácil, envolvendo uma chamada externa para sed ou um loop.

    #!/bin/sh
    quote_simple_command () {
      quoted=
      for raw in "$@"; do
        quoted="$quoted'"
        while case "$raw" in *\'*) true;; *) false;; esac; do
          quoted="$quoted${raw%%\'*}'\\''"
          raw="${raw#*\'}"
        done
        quoted="$quoted$raw' "
      done
      printf %s "${quoted% }"
    }
    setup_and_run() {
        some_setup_commands
        cat >>rerun.sh <<EOF
    some_setup_commands
    $(quote_simple_command "$@")
    EOF
        "$@"
    }
    
    • 7

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

    Matriz JSON para bash variáveis ​​usando jq

    • 4 respostas
  • Marko Smith

    A data pode formatar a hora atual para o fuso horário GMT? [duplicado]

    • 2 respostas
  • Marko Smith

    bash + lê variáveis ​​e valores do arquivo pelo script bash

    • 4 respostas
  • Marko Smith

    Como posso copiar um diretório e renomeá-lo no mesmo comando?

    • 4 respostas
  • Marko Smith

    conexão ssh. Conexão X11 rejeitada devido a autenticação incorreta

    • 3 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Marko Smith

    comando systemctl não funciona no RHEL 6

    • 3 respostas
  • Marko Smith

    rsync porta 22 e 873 uso

    • 2 respostas
  • Marko Smith

    snap /dev/loop em 100% de utilização -- sem espaço livre

    • 1 respostas
  • Marko Smith

    chave de impressão jq e valor para todos no subobjeto

    • 2 respostas
  • Martin Hope
    EHerman Matriz JSON para bash variáveis ​​usando jq 2017-12-31 14:50:58 +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
    Drux A data pode formatar a hora atual para o fuso horário GMT? [duplicado] 2017-12-26 11:35:07 +0800 CST
  • Martin Hope
    AllisonC Como posso copiar um diretório e renomeá-lo no mesmo comando? 2017-12-22 05:28:06 +0800 CST
  • Martin Hope
    Steve Como as permissões de arquivo funcionam para o usuário "root"? 2017-12-22 02:46:01 +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
  • Martin Hope
    Cbhihe Altere o editor padrão para vim para _ sudo systemctl edit [unit-file] _ 2017-12-03 10:11:38 +0800 CST
  • Martin Hope
    showkey Como baixar o pacote não instalá-lo com o comando apt-get? 2017-12-03 02:15:02 +0800 CST
  • Martin Hope
    youxiao Por que os diretórios /home, /usr, /var, etc. têm o mesmo número de inode (2)? 2017-12-02 05:33:41 +0800 CST
  • Martin Hope
    user223600 gpg — o comando list-keys gera uid [ desconhecido ] depois de importar a chave privada para uma instalação limpa 2017-11-26 18:26:02 +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