Refiro-me ao uso do comando GNU env
ou BSD env
na forma de:
env [name=value ...] [utility [args ...]]
Parece que não há como escapar caracteres especiais em value
parte, mas não tenho certeza de como env
é implementado para analisar a value
parte.
Eu sei que existem muitas maneiras de fazer isso pelo recurso do shell, mas quero passar uma string literal sem a ajuda do shell (um pouco como execute env
by exec
). Ou seja, preciso encontrar algum tipo de formato de string literal com nova linha e suportado por env
comando. Por exemplo:
env FOO=LITERAL_STRING ruby -e 'puts ENV["FOO"]'
Aqui o LITERAL_STRING
deve conter uma string literal com nova linha e env
deve entender esse formato.
Com o comando acima, a saída esperada deve ser:
hello
world
Eu me pergunto se é possível. Agradeceria sua ajuda.
Meio Ambiente
env
Eu uso BSD
env
para que não possa imprimir a versão. Não sei seman
pode ajudar:$ man env | tail -n1 BSD April 17, 2008 BSD
SO
$ sw_vers ProductName: macOS ProductVersion: 11.6 BuildVersion: 20G165
Seu entendimento está incorreto. Quando você armazena o conteúdo
"hello\nworld"
em uma variável, o\n
é interpretado literalmente. Somente se você invocar ferramentas comoprintf
ouecho
com-e
sinalizador, elas expandirão essas sequências de barra invertida ao imprimir no console.No seu caso, você deseja passar a variável para o ambiente com o caractere de nova linha expandido, sugira usar o estilo ANSI C citando no bash para isso
Ou se a portabilidade for um problema, uma solução trivial é colocar essas novas linhas onde você quiser
GNU's e FreeBSD's
env
têm uma-S
opção ("split")[1] que divide seu argumento em espaços e então interpreta muitos escapes nas strings resultantes, incluindo, mas não limitado a\n
:[1] seu uso principal é para
#! ...
linhas shebang, mas pode ser usado em outros lugares onde uma linha de comando é esperada, mas um analisador ad-hoc em vez de um shell é usado para interpretá-lo, como a-e
opção da maioria dos baseados em vte terminais.O
env
comando, quando executado, recebe vários argumentos --assim como qualquer comando-- daexecve()
chamada do sistema. O processo que o executa fará algo como:E
env
, por sua vez, fará (geralmente no mesmo processo):onde
modified_environ
éenviron
mas comvar=value
anexado a ele, ou se já havia uma ou mais strings começando comvar=
inenviron
, a primeira delas (pelo menos) substituída porvar=value
.Esses argumentos são matrizes de bytes terminadas em NUL, portanto, os únicos bytes que eles não podem conter são o byte NUL. O mesmo se aplica a variáveis de ambiente cujo nome nem valor podem conter bytes NUL.
env
, na inicialização, processa seus argumentos do primeiro ao último.Aqueles no início que começam com
-
seriam tomados como opções.-
sozinho também é tratado como a forma antiga de-i
ignorarenviron
.As opções seguintes (ou
--
que podem ser usadas para marcar o fim das opções) que contenham pelo menos uma=
serão consideradas como env var strings (para colocarmodified_environ
acima). O primeiro argumento não opcional que não contém um=
caractere é considerado como o nome do comando (que será passado como primeiro argumento para o comando e também usado para pesquisar o caminho do executável em$PATH
).Qualquer argumento depois disso será passado como argumentos para o comando, mesmo que comece com
-
ou contenha=
caracteres.Portanto, por
env
si só, apenas os caracteres-
e=
são especiais;-
somente durante o processamento da opção e=
somente até que o nome do comando seja localizado.Para poder passar um nome de variável de ambiente que comece com
-
ou um nome de comando que comece com-
, você pode simplesmente usar--
:Com várias
env
implementações,-
seguir sozinho--
ainda não seria considerado como um nome de comando. Então, se você quisesse chamar o comando chamado-
, você precisaria passar pelo menos uma variável de ambiente antes:(ou use
/path/to/-
ou./-
em vez de-
e bypath$PATH
procure por esse-
comando).env
no entanto, não permite que você execute um comando cujo nome contenha=
caracteres e não possa passar uma string sem=
caracteres no arquivomodified_environ
. Não há como escapar do=
personagem nesses casos.Mas no seu caso de
env
FOO=LITERAL_STRING
, não háLITERAL_STRING
outro caractere além do byte NUL que seria um problema no que diz respeito aenv
si mesmo.Agora, ao escrever código em algum idioma para executar esse
env
comando, provavelmente haverá caracteres nesse idioma que não podem ser inseridos literalmente.Por exemplo, em
perl
, você faria:Com o caractere de nova linha expresso
\n
entre aspas duplas, embora você também possa fazer:Para passar strings que contêm caracteres de nova linha.
Na sintaxe de linguagens de shell do tipo Bourne, o caractere de nova linha não é especial quando está entre aspas simples ou duplas (como para os operadores ou aspas de
q(...)
) , então você pode fazer:qq(...)
perl
Seria uma questão diferente no shell C ou no shell rc, onde
"..."
não há um operador de cotação.Seu
env FOO=LITERAL_STRING ruby -e 'puts ENV["FOO"]'
se parece com o código em uma linguagem shell. Essa sintaxe seria válida com a maioria dos shells, pois praticamente todos entendem o espaço como delimitadores de palavras e'...'
como um operador de aspas.Quando você omite
exec
no início, os shells executam o comando em um processo filho e, em seguida, esperam que esse processo termine ou seja suspenso.Se
env FOO=LITERAL_STRING ruby -e 'puts ENV["FOO"]'
for para um idioma que não permite inserir caracteres de nova linha literalmente (provavelmente não um shell) nem usar alguma forma de codificação (\n
,%0a
,
...), mas aparentemente suporta'...'
como um operador de citação como a maioria dos shells, além do BSDenv -S
truque já sugerido por @UncleBilly , você pode invocar um interpretador ou uma linguagem que pode executar comandos e permite especificar uma nova linha de alguma forma codificada, comoperl
,ruby
,python
,ksh93
,zsh
,bash
...Já que você já tem
ruby
:Mas qualquer linguagem de programação descendente, inclusive,
ruby
pode definir variáveis de ambiente por si só, então você não precisaenv
:Use uma nova linha literal no valor:
Resultado:
Se você tiver uma string com
\n
a qual deseja converter em uma nova linha real, use um utilitário comoprintf
, assim como faria em qualquer outro lugar:env
não é especial a esse respeito (na verdade,env
só vê a nova linha real, porque é expandida antes do início do processo).