tcsh はコマンド置換で改行を保持します `...`

tcsh はコマンド置換で改行を保持します `...`

shそこで、スタイルのステートメントをforexport key=valueに変換する簡単なスクリプトを作成しました。csh-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`'

そして次の出力を生成します

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`

私の場合、.tcshrcこのスクリプトをエイリアス にバインドしましたdocker-machine-env-csh

このスクリプトの出力を一時変数を使ってソース化することは問題なくできる

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

evalしかし、このエイリアスの結果を直接見ることはできないようです

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

または、改行を保持する方法で変数に割り当てます。

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

ただし、奇妙なことに、printf "%s\n" `docker-machine-env-csh`トークンごとに改行が挿入されるようです。

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

tcshコマンド置換で改行を保持するにはどうすればよいですか?

答え1

cshまたはをスクリプトに使用しないことが推奨される理由はたくさんありますtcsh。これはそのうちの 1 つです。

verbatimの出力some commandを のシェル変数に取得するにはtcsh、次のようなものが必要です。

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

$var:q次のように変数を展開する構文を使用することを忘れないでください。

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

POSIX ではsh次のようになります。

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

さて、docker-machine-env-cshコマンドが情報を 1 行のみで出力した場合、または少なくとも各行が と;コメントなしで終了し、スペースで結合しても有効な csh コードになる場合 ( や などのアプリケーションがdircolors出力をのssh-agentに渡す場合に行うように)、次のように実行できます。csheval

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

を使用するとset var = `docker-machine-env-csh`tcsh空白で分割されます (配列変数が作成されます)。一方set var = "`docker-machine-env-csh`"、 を使用すると、改行のみで分割されます (配列変数のままですが、出力に 1 行しかない場合、その配列には 1 つの要素しかありません)。

ここでは、 には改行文字が含まれていないため、"$var"の代わりにを使用できます。は配列要素をスペースで結合しますが、は配列要素を保持します (ここでは要素が 1 つしかないため、違いはありません)。これらの配列要素に改行が含まれている可能性があり、スペースで結合したい場合は、 を使用します。$var:q$var"$var"$var:q"$var:q"

したがって、スクリプトを次のように変更することができます。

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

関連情報