60057
## 前提

Ubuntu で、Bash と Dash ではシェル組み込みの echo コマンドの挙動が異なります。特に Bash の echo は `-e`
オプションが無いとエスケープシーケンスを解釈しませんが、Dash の echo はデフォルトでエスケープシーケンスを解釈します。この挙動は Bash を
`--posix` モードで起動しても変わりません。

```

    $ bash --posix -c "echo 'a\nb'"
    a\nb
    $ dash -c "echo 'a\nb'"
    a
    b
    
```

## 質問

なぜ Bash の echo は ~~POSIX に反して~~ デフォルトではエスケープシーケンスを解釈しないのでしょうか？ あるいは、なぜ ~~POSIX
の~~ Dash の echo はエスケープシーケンスを解釈するのでしょうか。どういう意図があってそのようなデフォルト動作にしているのか知りたいです。

※歴史的にどちらの echo の方が古いと言えるのか分からなかったのでこのような書き方をしていますが、「なぜ同じ挙動にしなかったの？」というのが疑問です。

※追記：回答を受けて私が POSIX の echo について少し勘違いをしていたことが分かったので、打ち消し線で直しました。

## 参考

挙動を確かめた環境は Ubuntu 18.04、Bash 4.4.20(1)-release、Dash 0.5.8-2.10 です。

それぞれの説明はマニュアルにも書かれています。

`man bash`：

> echo [-neE] [arg ...]
>
> Output the args, separated by spaces, followed by a newline. (中略) **If the
> -e option is given, interpretation of the following backslash-escaped
> characters is enabled.** The -E option disables the interpretation of these
> escape characters, even on systems where they are interpreted by default.
> The xpg_echo shell option may be used to dynamically determine whether or
> not echo expands these escape characters by default. echo does not interpret
> -- to mean the end of options. echo interprets the following escape
> sequences: (後略)

`man dash`：

> echo [-n] args...
>
> Print the arguments on the standard output, separated by spaces. (中略) **If
> any of the following sequences of characters is encountered during output,
> the sequence is not output. Instead, the specified action is performed:**
> (後略)

この `man bash` に書かれている通り、シェルオプション `xpg_echo` を有効化すると Bash
でもオプション無しでエスケープシーケンスを解釈しました。

```

    $ bash --posix -c "shopt -s xpg_echo && echo 'a\nb'"
    a
    b
    $ bash -c "shopt -s xpg_echo && echo 'a\nb'"
    a
    b
    
```

echo コマンドの実装による挙動の差は、次のブログ記事が詳しいです：[echo
コマンドの違いと移植性の問題](https://fumiyas.github.io/2013/12/08/echo.sh-advent-
calendar.html)
CC BY-SA 4.0
2019-10-28T18:43:54.137
60054
2019-10-30T01:33:09.220
2019-10-29T00:44:44.623
19110
19110
question
bash posix dash
BashとDashでechoのエスケープシーケンスに対する挙動が異なるのは何故？
# 歴史

もともとechoはどのようなオプションもエスケープシーケンスも解釈せず、ただ引数を標準出力に渡すだけの単純なものでした。Version 6
Unixのecho.cにはforループとprintfしかありません。V6は1975年にリリースされています。

<https://www.in-ulm.de/~mascheck/various/echo+printf/>

> About the history, from Gunnar Ritter in <3B98D626.HL11B46E@bigfoot.de>
> (rough translation by me), motivating this page:  
>  "Research Unix -> 32v -> BSD had "-n",  
>  PWB/Unix -> System III -> System V [had] the escape sequences  
>  and then it became a jumble."
>
> [6th edition echo](http://minnie.tuhs.org/cgi-
> bin/utree.pl?file=V6/usr/source/s1/echo.c) research unix didn't know any
> features.  
>  [7th edition echo](http://minnie.tuhs.org/cgi-
> bin/utree.pl?file=V7/usr/src/cmd/echo.c) implemented -n  
>  [PWB/Unix1.0 echo](http://minnie.tuhs.org/cgi-
> bin/utree.pl?file=PWB1/sys/source/s1/echo.c) (derived from 6th edition)
> implemented \n, \c, \, and \0xx  
>  [System III](https://www.in-
> ulm.de/~mascheck/various/echo+printf/src/sys3-echo.c.html) (and SVR1) echo
> knew \b, \c, \f, \n, \r, \t, \, and \0xx

その後BSDはV7を踏襲して `-n` オプションを追加し、System
Vに繋がるPWB/Unixはいくつかのエスケープシーケンスを解釈するようになったのがわかります。

POSIX.1がリリースされたのは1988年です。echoの実装についてPOSIXは **いかなるオプションも許容していません** 。ただし、`-n`
とエスケープシーケンスについては実装依存として逃げ道を作っています。

<https://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html>

> Implementations shall not support any options.
>
> If the first operand is -n, or if any of the operands contain a <backslash>
> character, the results are implementation-defined.

# 質問に対する回答

## なぜ Bash の echo は POSIX に反してデフォルトではエスケープシーケンスを解釈しないのでしょうか？

XPG_ECHO(または前身のV9_ECHO)シェルオプションから察するに、エスケープシーケンスの追加が上位互換性の破壊に繋がるのを嫌ったものと解釈できます。

## あるいは、なぜ POSIX の echo はエスケープシーケンスを解釈するのでしょうか。

[POSIXはSystem
Vを起点としている](https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html)からです。

> The System V shell was selected as the starting point for the Shell and
> Utilities volume of POSIX.1-2017.

## なぜ同じ挙動にしなかったの？

上位互換性の維持と利便性の向上の間で、異なる実装の足並みが揃わなかったから。じゃないでしょうか。  
同じ挙動が必要なら printf があるというのも理由かもしれません。
CC BY-SA 4.0
2019-10-28T20:52:43.607
60057
2019-10-30T01:33:09.220
2019-10-30T01:33:09.220
3061
62
60054
answer