次の簡単なスクリプトがあるとしますtmp.sh
。
echo "testing"
stat .
echo "testing again"
それは単純ですが\r\n
(つまり、CRLF、つまりキャリッジリターン+ラインフィード)で終わります。 Webページは行末を保持しないため、以下は16進ダンプです。
$ hexdump -C tmp.sh
00000000 65 63 68 6f 20 22 74 65 73 74 69 6e 67 22 0d 0a |echo "testing"..|
00000010 73 74 61 74 20 2e 0d 0a 65 63 68 6f 20 22 74 65 |stat ...echo "te|
00000020 73 74 69 6e 67 20 61 67 61 69 6e 22 0d 0a |sting again"..|
0000002e
これで、スクリプトはWindowsのMSYS2で起動および開発されたため、CRLF行の終わりがあります。したがって、Windows 10のMSYS2で実行すると、予想される結果が得られます。
$ bash tmp.sh
testing
File: .
Size: 0 Blocks: 40 IO Block: 65536 directory
Device: 8e8b98b6h/2391513270d Inode: 281474976761067 Links: 1
Access: (0755/drwxr-xr-x) Uid: (197609/ USER) Gid: (197121/ None)
Access: 2020-04-03 10:42:53.210292000 +0200
Modify: 2020-04-03 10:42:53.210292000 +0200
Change: 2020-04-03 10:42:53.210292000 +0200
Birth: 2019-02-07 13:22:11.496069300 +0100
testing again
ただし、このスクリプトをUbuntu 18.04システムにコピーして実行すると、他の結果が表示されます。
$ bash tmp.sh
testing
stat: cannot stat '.'$'\r': No such file or directory
testing again
同じ行末を持つ他のスクリプトのUbuntu bashでもこのエラーが発生しました。
line 6: $'\r': command not found
…おそらく空の行から来たのでしょう。
そのため、Ubuntuの何かがEnterに停止したようです。私は見たBASHとキャリッジリターン動作:
Bashとは何の関係もありません。 \r および \n は Bash ではなく端末で解釈されます。
...しかし、これはコマンドラインにそのまま入力された内容にのみ適用されるようです。\r
そしてこれは\n
すでにスクリプト自体に入力されているので、Bashはこれをここで解釈する必要があります\r
。
UbuntuのBashバージョンは次のとおりです。
$ bash --version
GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
...MSYS2のBashバージョンは次のとおりです。
$ bash --version
GNU bash, version 4.4.23(2)-release (x86_64-pc-msys)
(それらの間のギャップはそれほど大きくないようです...)
\r
とにかく私の質問は - Ubuntu / LinuxのBashを「印刷可能な文字」として解釈するのではなく、これを無視するように説得する方法はありますか?こう説明します)?編集する:いいえスクリプト自体を変換する必要があります(たとえば、gitでこの方法でチェックすると、CRLF行の末尾に変更されていません)。
EDIT2:私は一緒に作業している他の人がWindowsのテキストエディタでスクリプトを再開し、\r\n
スクリプトを再導入してコミットできるので、この方法を好みます。これにより、無限のコミットストリームが発生する可能性があります。リザーバーを汚染する\r\n
変換です\n
。
編集2:@ Kusalanandaがコメントでdos2unix
()を言及しましたsudo apt install dos2unix
。次のように書いてください。
$ dos2unix tmp.sh
dos2unix: converting file tmp.sh to Unix format...
...ファイルを内部で変換してstdoutに出力します。 stdinリダイレクトを設定する必要があります。
$ dos2unix <tmp.sh | hexdump -C
00000000 65 63 68 6f 20 22 74 65 73 74 69 6e 67 22 0a 73 |echo "testing".s|
00000010 74 61 74 20 2e 0a 65 63 68 6f 20 22 74 65 73 74 |tat ..echo "test|
00000020 69 6e 67 20 61 67 61 69 6e 22 0a |ing again".|
0000002b
...その後、原則としてUbuntuで実行できます。この場合はうまくいくようです。
$ dos2unix <tmp.sh | bash
testing
File: .
Size: 20480 Blocks: 40 IO Block: 4096 directory
Device: 816h/2070d Inode: 1572865 Links: 27
Access: (1777/drwxrwxrwt) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2020-04-03 11:11:00.309160050 +0200
Modify: 2020-04-03 11:10:58.349139481 +0200
Change: 2020-04-03 11:10:58.349139481 +0200
Birth: -
testing again
しかし、覚えておくべき少し混乱したコマンドに加えて、stdinはもはや端末ではないので、bashの意味も変わります。この簡単な例では動作します。https://stackoverflow.com/questions/23257247/pipe-a-script-into-bashより大きな質問のような。
ベストアンサー1
私が知っている限り、BashにWindowsスタイルの行末を許可するように指示する方法はありません。
Windowsが関連している場合は、autocrlf
設定フラグを使用してコミット時に行末を自動的に変換するGitの機能に依存するのが一般的な方法です。例を見る行末のGitHubドキュメント、これはGitHubに限定されません。このようにして、ファイルはリポジトリからUnixスタイルの行末にコミットされ、各クライアントプラットフォームに合わせて変換されます。
(その逆は問題ではありません。MSYS2はWindowsでUnixスタイルの行末をうまく処理します。)