43409


Anaconda
で使われている[シェルスクリプト](https://github.com/conda/conda/blob/caedbbfe37860f3b61466408cc9ae199b3ffe910/conda/shell/etc/profile.d/conda.sh)のソースコードを眺めていたところ、`eval`、`export`、`local`
などのコマンド名の前にバックスラッシュが付けられていることに気づきました。

[code]

    \export CONDA_SHLVL=0
    
[/code]

この行頭のバックスラッシュにはどのような意味がありますか？


CC BY-SA 3.0
2018-04-19T18:58:57.823
43408
2018-04-20T02:22:58.780
2018-04-19T20:43:18.553
19110
19110
question
shellscript
シェルスクリプトの先頭にバックスラッシュをつけているのは何故？


よくあるのは、スクリプトが **インタラクティブに** 実行される際、そのコマンドが alias されていても無視する、という意味です (Anaconda
のリポジトリのコミット・メッセージに言及が無いため本当のところは分かりません)。なお、インタラクティブでない場合においては設定しない限り alias
が展開されないため、バックスラッシュがあってもなくても同じです。

ただし、alias を回避するという意味ではバックスラッシュではなく [`command`
コマンド](https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html#lbDB) /
[`builtin` コマンド](https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html#lbDB)や
[`shopt -u
expand_aliases`](https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html#lbDB)
を使うべきだと思います。

## 詳細な説明

[POSIX
シェルの仕様](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_03_01)は、alias
の代入について以下のように書いています。

> After a token has been delimited, but before applying the grammatical rules
> in [Shell
> Grammar](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_10),
> a resulting word that is identified to be the command name word of a simple
> command shall be examined to determine whether it is an unquoted, valid
> alias name.

つまり alias
によってコマンドが書き換えられるのは、トークン分割の直後です。バックスラッシュは文字をエスケープしますが、トークン分割時は例外を除いてエスケープの変換がなされないため、たとえば
`\export` は `\export` のまま alias があるかどうか判定されることになります。したがってたとえ `export` に alias
があったとしても、`\export` は変換されません。そしてこの後エスケープが処理され、`export` が呼び出されることになります。

ここからは余談ですが、上の仕組みを見ると実はコマンドの先頭にバックスラッシュを持ってくる必要性は無いことに気づきます。先頭にバックスラッシュを置く方法がよく使われているというだけです。たとえば
`export` にしか alias が無いのであれば、次のように書くとどれも alias を回避します。

[code]

    \export
    ex\port
    \e\x\p\o\r\t
    "export"
    "e"xport
    'ex'port
    'ex'"port"
    
[/code]

なお、バックスラッシュで alias による変換は避けられても、 **シェルの関数による変換は避けられていない**
ことに注意してください。両者共に回避したい場合、[`command`
コマンド](https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html#lbDB) や
[`builtin`
コマンド](https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html#lbDB)を使う方法があります。ただし
`command`
という名前のシェル関数が定義されていると上手く動きません。詳しくは[この投稿](https://stackoverflow.com/a/35931876/5989200)をご覧ください。

## 関連した投稿

  * ["Why start a shell command with a backslash?"](https://stackoverflow.com/q/15691977/5989200) \-- Stack Overflow


CC BY-SA 3.0
2018-04-19T18:58:57.823
43409
2018-04-20T02:22:58.780
2018-04-20T02:22:58.780
19110
19110
43408
answer