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 / 717700
Accepted
user536152
user536152
Asked: 2022-09-19 00:51:41 +0800 CST2022-09-19 00:51:41 +0800 CST 2022-09-19 00:51:41 +0800 CST

Função Bash/argumento de script copiado completamente na variável

  • 772

Como fazer com que o argumento da função/script Bash seja copiado completamente para a variável, pois '(e algum outro caractere) não pode reter estar na variável?
por exemplo

m() {
 v="$@"
 echo "$v"
}

$ m let it be 'foo' bar
let it be foo bar

A ajuda sincera é apreciada, obrigado antes.

bash variable
  • 4 4 respostas
  • 196 Views

4 respostas

  • Voted
  1. Best Answer
    ilkkachu
    2022-09-19T07:42:50+08:002022-09-19T07:42:50+08:00

    A coisa a notar aqui é que quando você executa, por exemplo

    m let it be 'foo bar'
    

    o programa mnão obtém a linha de comando inteira, mas o shell analisa a linha de comando primeiro, processando aspas, expansões de variáveis ​​e coisas assim. O resultado final que vai para o comando é mais como um array de strings separadas, que nesse caso seria [ let, it, be, foo bar].

    Da mesma forma, em

    f="James Matthew"
    l="Bond"
    m "$l, $f $l"
    

    mapenas veria [ Bond, James Matthew Bond], e não teria ideia das variáveis ​​e cotações envolvidas.

    Isso significa que um programa regular não tem como chegar à linha de entrada bruta.


    Existem soluções alternativas para o zsh com manipuladores pré-executivos em Qualquer shell em que as expansões são desativadas sem escapar ou citar? e zsh: alias ou shell function para apenas ecoar sua linha de comando, incluindo caracteres de controle do shell , mas não acho que vi um para o Bash.

    O mais próximo que você obtém é o DEBUGtrap, que vê o comando a ser executado antes de expansões, processamento de cotações e redirecionamentos. No entanto, não está completo, pois vê apenas um único comando simples de cada vez. Os comentários serão removidos antes de vê-los, e um sem aspas ;, &, |, &&, ||ou (( )pelo menos) ainda será analisado.

    De qualquer forma, podemos tentar:

    #!/bin/bash
    
    shopt -s extdebug
    
    handle_@ () {
        local re='[[:space:]]*@ ([^[:space:]]+)[[:space:]]+(.*)'
        if [[ $BASH_COMMAND =~ $re ]]; then
            "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
            return 1
        fi
    }
    m() {
        printf "<%s>\n" "$1"
    }
    
    trap handle_@ DEBUG
    
    @ m 'foo bar' doo "$var" > /dev/null
    @ m what about this?; date
    @ m or some (parentheses)?
    

    O script usa o DEBUGtrap para detectar comandos que começam com @ , pega a próxima "palavra" separada por espaço como um comando a ser executado e passa o restante como um único argumento para ele. Retornar 1do manipulador de trap diz ao shell para não executar o comando da maneira normal, evitando uma provável mensagem de erro e bloqueando a execução de quaisquer expansões incorporadas (isso requer extdebugconfiguração).

    A saída é algo assim, mostrando que o dateapós o ponto e vírgula é executado e que o parêntese quebra a sintaxe:

    <'foo bar' doo "$var" > /dev/null>
    <what about this?>
    Sun Sep 18 18:39:38 EEST 2022
    debugprint.sh: line 20: syntax error near unexpected token `('
    debugprint.sh: line 20: `@ m or some (parentheses)?'
    

    Para ser honesto, isso é um pouco nojento, as restrições com os caracteres especiais são bastante arbitrárias, e não garanto que o script não tenha outros problemas também.


    Em geral, se você está planejando isso para algum tipo de uso em produção, sugiro reconsiderar a estrutura do programa e passar a string por um arquivo ou, por exemplo, um here-doc, dependendo do que você está fazendo.

    Um here-doc torna relativamente fácil alimentar uma string bruta, embora passe pelo comando stdin:

    m() {
        m=$(cat) 
        printf "<%s>\n" "$m"
    }
    m <<'EOF'
    Say "$hello" to my 'little friend'
    EOF
    

    Que imprime

    <Say "$hello" to my 'little friend'>
    

    Com a string delimitadora here-doc entre aspas (em <<'EOF'), isso permite que você coloque texto e caracteres arbitrários sem a necessidade de se preocupar com aspas. (Além da própria string delimitadora, é claro, mas você pode usar uma gerada aleatoriamente em vez de EOF.)

    • 3
  2. Arkadiusz Drabczyk
    2022-09-19T01:29:12+08:002022-09-19T01:29:12+08:00

    Você precisa convencer o shell de que uma aspa simples é uma parte do valor da variável assim:

    m let it be "'foo'" bar
    
    • 2
  3. Andre Beaud
    2022-09-19T01:32:39+08:002022-09-19T01:32:39+08:00

    O shell está interpretando as 'aspas antes que a função as veja e fará o mesmo com eg "e \. Você pode escapar deles com \, por exemplo

    $ m let it be \'foo\' bar
    let it be 'foo' bar
    
    and
    
    $ m let it be \"foo\" bar, \' \\ \"$foo\" \"\$foo\"
    let it be "foo" bar, ' \ "" "$foo"
    
    • 2
  4. terdon
    2022-09-19T02:33:26+08:002022-09-19T02:33:26+08:00

    O problema aqui é que você está passando a entrada sem aspas. Como resultado, o 'está sendo consumido pelo shell antes de chamar sua função. O mesmo aconteceria se você tivesse usado um ", e também falharia se você tivesse usado caracteres globbing como *ou ?:

    $ ls
    file1  file2
    
    $ m "aa"bb
    aabb
    
    $ m f*2
    file2
    

    A solução mais limpa, pelo menos para mim, é sempre passar sua entrada citada. Isso protegerá quaisquer caracteres com significado especial do shell e, assim, garantirá que eles sejam passados ​​inalterados para sua função:

    $ m '"aa"bb'
    "aa"bb
    
    $ m "foo 'bar' baz"
    foo 'bar' baz
    
    $ m "f*2"
    f*2
    
    • 2

relate perguntas

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

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

  • Como salvar um caminho com ~ em uma variável?

  • 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