Descobri que as novas linhas estavam sendo removidas quando fiz "eco $ VAR". Se, em vez disso, citei $ VAR, ele preservou as novas linhas.
Brent
2
Isso não está 100% certo. A substituição de comando sempre remove novas linhas finais.
TheBonsai
8
Isso cria um subshell; existe alguma maneira de fazer isso no mesmo shell?
lmat - Reintegração de Monica
24
Você pode usar funções bash em comandos / pipelines da mesma forma que usaria programas normais. As funções também estão disponíveis para subshells e transitivamente, Substituição de Comando:
VAR=$(scan)
É a maneira direta de obter o resultado desejado na maioria dos casos. Vou delinear casos especiais abaixo.
Preservando Newlines à direita:
Um dos efeitos colaterais (geralmente úteis) da Substituição de Comando é que ela removerá qualquer número de novas linhas finais. Se alguém deseja preservar as novas linhas finais, pode anexar um caractere fictício à saída do subshell e, subsequentemente, removê-lo com a expansão do parâmetro.
functionscan2 () {
local nl=$'\x0a'; # that's just \necho"output${nl}${nl}"# 2 in the string + 1 by echo
}
# append a character to the total output.# and strip it with %% parameter expansion.
VAR=$(scan2; echo"x"); VAR="${VAR%%x}"echo"${VAR}---"
impressões (3 novas linhas mantidas):
output
---
Use um parâmetro de saída: evitando o subshell (e preservando novas linhas)
Se o que a função tenta alcançar é "retornar" uma string em uma variável, com bash v4.3 e superior, pode-se usar o que é chamado de a nameref. Namerefs permite que uma função receba o nome de um ou mais parâmetros de saída de variáveis. Você pode atribuir coisas a uma variável nameref, e é como se você alterasse a variável para a qual ela 'aponta / referencia'.
functionscan3() {
local -n outvar=$1# -n makes it a nameref.local nl=$'\x0a'
outvar="output${nl}${nl}"# two total. quotes preserve newlines
}
VAR="some prior value which will get overwritten"# you pass the name of the variable. VAR will be modified.
scan3 VAR
# newlines are also preserved.echo"${VAR}==="
estampas:
output
===
Este formulário tem algumas vantagens. Ou seja, ele permite que sua função modifique o ambiente do chamador sem usar variáveis globais em todos os lugares.
Nota: o uso de namerefs pode melhorar muito o desempenho de seu programa se suas funções dependerem muito de bash builtins, porque evita a criação de um subshell que é descartado logo depois. Isso geralmente faz mais sentido para pequenas funções reutilizadas com frequência, por exemplo, funções que terminam emecho "$returnstring"
o localintegrado aceitará todas as opções que o declareintegrado aceitar. a partir de um teste rápido, também parece que declare -nem um escopo de função também dá o escopo local variável. parece que eles são intercambiáveis aqui.
Respostas:
Exatamente da mesma forma que nos programas.
fonte
Você pode usar funções bash em comandos / pipelines da mesma forma que usaria programas normais. As funções também estão disponíveis para subshells e transitivamente, Substituição de Comando:
É a maneira direta de obter o resultado desejado na maioria dos casos. Vou delinear casos especiais abaixo.
Preservando Newlines à direita:
Um dos efeitos colaterais (geralmente úteis) da Substituição de Comando é que ela removerá qualquer número de novas linhas finais. Se alguém deseja preservar as novas linhas finais, pode anexar um caractere fictício à saída do subshell e, subsequentemente, removê-lo com a expansão do parâmetro.
function scan2 () { local nl=$'\x0a'; # that's just \n echo "output${nl}${nl}" # 2 in the string + 1 by echo } # append a character to the total output. # and strip it with %% parameter expansion. VAR=$(scan2; echo "x"); VAR="${VAR%%x}" echo "${VAR}---"
impressões (3 novas linhas mantidas):
Use um parâmetro de saída: evitando o subshell (e preservando novas linhas)
Se o que a função tenta alcançar é "retornar" uma string em uma variável, com bash v4.3 e superior, pode-se usar o que é chamado de a
nameref
. Namerefs permite que uma função receba o nome de um ou mais parâmetros de saída de variáveis. Você pode atribuir coisas a uma variável nameref, e é como se você alterasse a variável para a qual ela 'aponta / referencia'.function scan3() { local -n outvar=$1 # -n makes it a nameref. local nl=$'\x0a' outvar="output${nl}${nl}" # two total. quotes preserve newlines } VAR="some prior value which will get overwritten" # you pass the name of the variable. VAR will be modified. scan3 VAR # newlines are also preserved. echo "${VAR}==="
estampas:
Este formulário tem algumas vantagens. Ou seja, ele permite que sua função modifique o ambiente do chamador sem usar variáveis globais em todos os lugares.
Nota: o uso de namerefs pode melhorar muito o desempenho de seu programa se suas funções dependerem muito de bash builtins, porque evita a criação de um subshell que é descartado logo depois. Isso geralmente faz mais sentido para pequenas funções reutilizadas com frequência, por exemplo, funções que terminam em
echo "$returnstring"
Isso é relevante. https://stackoverflow.com/a/38997681/5556676
fonte
Acho que init_js deve usar declare em vez de local!
function scan3() { declare -n outvar=$1 # -n makes it a nameref. local nl=$'\x0a' outvar="output${nl}${nl}" # two total. quotes preserve newlines }
fonte
local
integrado aceitará todas as opções que odeclare
integrado aceitar. a partir de um teste rápido, também parece quedeclare -n
em um escopo de função também dá o escopo local variável. parece que eles são intercambiáveis aqui.