tcsh preserva novas linhas na substituição de comando '…'

2

Então, escrevi um script simples para converter as expressões sh -style export key=value para csh-style setenv key value para docker-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 .tcshrc , vinculei esse script ao alias docker-machine-env-csh .

Eu posso gerar a saída deste script usando uma variável temporária bem

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

No entanto, parece que não consigo diretamente eval o resultado desse alias

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

Ou atribuí-lo a uma variável de forma a preservar 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 todos os tokens.

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

Como preservo as novas linhas na substituição do comando tcsh ?

    
por Gregory Nisbet 19.05.2016 / 18:27

1 resposta

6

Existem vários motivos pelos quais não é recomendado usar csh ou tcsh para o script. Esse é um desses.

Para obter a saída de some command verbatim em uma variável de shell em 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 a sintaxe $var:q para expandir a variável como em:

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

O POSIX sh equivalente seria:

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

Agora, se o comando docker-machine-env-csh emitiu as informações apenas em uma linha, ou pelo menos com cada linha terminada com ; e sem comentários, para que, quando unidos a espaços, ainda sejam códigos csh válidos (como aplicativos como dircolors ou ssh-agent do quando eles querem que sua saída seja passada para csh ' 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' , tcsh divide em espaços em branco (e cria uma variável de matriz), enquanto com set var = "'docker-machine-env-csh'" , ele divide somente em nova linha (ainda uma variável de matriz, mas se a saída tiver apenas uma linha, essa matriz tem apenas um elemento).

Aqui você pode usar "$var" no lugar de $var:q porque $var não contém caracteres de nova linha. "$var" uniria os elementos da matriz com espaço enquanto $var:q os preservaria (aqui há apenas um elemento, portanto não faz diferença). Se esses elementos da matriz pudessem conter novas linhas e você quisesse se juntar a eles 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'"'
    
por 19.05.2016 / 18:51