tcsh preserva novas linhas na substituição de comando `...`

tcsh preserva novas linhas na substituição de comando `...`

Então, escrevi um script simples para converter instruções sh-style em for .export key=valuecsh-style setenv key valuedocker-machine env

#!/bin/sh
docker-machine env | sed -e 's/export/setenv/' -e 's/=/ /' -e '$d'
echo '# eval `docker-machine env`'

e produz a seguinte saída

setenv DOCKER_TLS_VERIFY "1"
setenv DOCKER_HOST "tcp://<ipv4 address>:<port>"
setenv DOCKER_CERT_PATH "<HOME>/.docker/machine/machines/default"
setenv DOCKER_MACHINE_NAME "default"
# Run this command to configure your shell:
# eval `docker-machine env`

No meu, .tcshrcvinculei esse script ao alias docker-machine-env-csh.

Posso obter a saída deste script usando uma variável temporária perfeitamente

% docker-machine-env-csh >! /tmp/csh && source /tmp/csh

No entanto, não consigo entender diretamente evalo resultado desse alias

% eval `docker-machine-env-csh`
setenv: Too many arguments.

Ou atribua-o a uma variável de uma forma que preserve as novas linhas.

% set a = `docker-machine-env-csh`
% printf "%s\n" "$a"
setenv ... setenv ... setenv ...

Embora, estranhamente, printf "%s\n" `docker-machine-env-csh`pareça inserir uma nova linha entre cada token.

% printf "%s\n" `docker-machine-env-csh`
setenv
...
...
setenv
...
...

Como preservo novas linhas na tcshsubstituição de comandos?

Responder1

Existem muitos bons motivos pelos quais é recomendado não usar cshou tcshpara scripts. Esse é um desses.

Para obter a saída some commandliteral em uma variável shell tcsh, você precisa de algo como:

set temp = "`(some command; echo .) | paste -d . - /dev/null`"
set var = ""
set nl = '\
'
foreach i ($temp:q)
  set var = $var:q$i:r:q$nl:q
end
set var = $var:r:q

Não se esqueça de usar $var:qa sintaxe para expandir a variável como em:

printf '<%s>\n' $var:q

O equivalente POSIX shseria:

var=$(some command; echo .)
var=${var%.}

Agora, se o seu docker-machine-env-cshcomando produziu as informações em apenas uma linha, ou pelo menos com cada linha terminada com um ;e sem comentários para que quando unidos com espaços eles ainda sejam códigos csh válidos (como aplicativos como dircolorsou ssh-agentfazem quando desejam sua saída a ser passado para csh's eval), então você poderia fazer:

set var = "`docker-machine-env-csh`"
printf '%s\n' "$var"
# or printf '%s\n' $var:q
# or printf '%s\n' "$var:q"

Com set var = `docker-machine-env-csh`, tcshdivide-se em espaços em branco (e cria uma variável de matriz), enquanto com set var = "`docker-machine-env-csh`", ele divide apenas em nova linha (ainda uma variável de matriz, mas se a saída tiver apenas uma linha, essa matriz terá apenas um elemento).

Aqui você pode usar "$var"no lugar de $var:qporque $varnão contém caracteres de nova linha. "$var"juntaria os elementos do array com espaço enquanto $var:qos preservaria (aqui há apenas um elemento, então não faz diferença). Se esses elementos da matriz puderem conter novas linhas e você quiser juntá-los com espaço, você usaria "$var:q".

Então talvez você possa modificar seu script como:

#! /bin/sh -
docker-machine env | sed '
  s/export/setenv/
  s/=/ /
  /^#/!s/$/;/
  $d'
echo '# eval "`docker-machine env`"'

informação relacionada