sda*_*aau 9 linux bash msys newlines
假设我有以下简单的脚本tmp.sh:
echo "testing"\nstat .\necho "testing again"\nRun Code Online (Sandbox Code Playgroud)\n\n尽管它很简单,但它以\\r\\n(即 CRLF,即回车+换行)作为行结尾。由于网页不会保留行结尾,因此这里是一个十六进制转储:
$ hexdump -C tmp.sh \n00000000 65 63 68 6f 20 22 74 65 73 74 69 6e 67 22 0d 0a |echo "testing"..|\n00000010 73 74 61 74 20 2e 0d 0a 65 63 68 6f 20 22 74 65 |stat ...echo "te|\n00000020 73 74 69 6e 67 20 61 67 61 69 6e 22 0d 0a |sting again"..|\n0000002e\nRun Code Online (Sandbox Code Playgroud)\n\n现在,它具有 CRLF 行结尾,因为该脚本是在 Windows 上的 MSYS2 下启动和开发的。因此,当我在 Windows 10 上的 MSYS2 中运行它时,我得到了预期的结果:
\n\n$ bash tmp.sh\ntesting\n File: .\n Size: 0 Blocks: 40 IO Block: 65536 directory\nDevice: 8e8b98b6h/2391513270d Inode: 281474976761067 Links: 1\nAccess: (0755/drwxr-xr-x) Uid: (197609/ USER) Gid: (197121/ None)\nAccess: 2020-04-03 10:42:53.210292000 +0200\nModify: 2020-04-03 10:42:53.210292000 +0200\nChange: 2020-04-03 10:42:53.210292000 +0200\n Birth: 2019-02-07 13:22:11.496069300 +0100\ntesting again\nRun Code Online (Sandbox Code Playgroud)\n\n但是,如果我将此脚本复制到 Ubuntu 18.04 计算机并在那里运行它,我会得到其他内容:
\n\n$ bash tmp.sh\ntesting\nstat: cannot stat \'.\'$\'\\r\': No such file or directory\ntesting again\nRun Code Online (Sandbox Code Playgroud)\n\n在具有相同行结尾的其他脚本中,我在 Ubuntu bash 中也遇到了此错误:
\n\nline 6: $\'\\r\': command not found\nRun Code Online (Sandbox Code Playgroud)\n\n...可能来自空行。
\n\n所以,很明显,Ubuntu 中的某些东西在回车时会被卡住。我见过BASH 和回车行为:
\n\n\n\n\n它与 Bash 没有任何关系: \\r 和 \\n 由终端解释,而不是由 Bash 解释
\n
...但是,我想这仅适用于在命令行上逐字输入的内容;这里的\\r和\\n已经在脚本本身中输入了,所以 Bash 一定会解释这里\\r的。
这是 Ubuntu 中 Bash 的版本:
\n\n$ bash --version\nGNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)\nRun Code Online (Sandbox Code Playgroud)\n\n...这里是 MSYS2 中的 Bash 版本:
\n\n$ bash --version\nGNU bash, version 4.4.23(2)-release (x86_64-pc-msys)\nRun Code Online (Sandbox Code Playgroud)\n\n(他们看起来并没有那么遥远......)
\n\n无论如何,我的问题是 - 有没有办法说服 Ubuntu/Linux 上的 Bash 忽略\\r,而不是试图将其解释为(可以这么说)“可打印字符”(在本例中,意味着一个可能是有效命令的一部分,bash 如此解释)?编辑:无需转换脚本本身(因此它保持不变,带有 CRLF 行结尾,如果以这种方式检查,例如在 git 中)
EDIT2:我更喜欢这种方式,因为与我一起工作的其他人可能会在 Windows 文本编辑器中重新打开脚本,可能会\\r\\n再次重新引入脚本并提交它;然后我们可能会得到无休止的提交流,这可能只不过是污染存储库的\\r\\n转换\\n。
编辑2:@Kusalananda 在评论中提到dos2unix(sudo apt install dos2unix);请注意,只需这样写:
$ dos2unix tmp.sh \ndos2unix: converting file tmp.sh to Unix format...\nRun Code Online (Sandbox Code Playgroud)\n\n...将就地转换文件;要将其输出到 stdout,必须设置 stdin 重定向:
\n\n$ dos2unix <tmp.sh | hexdump -C\n00000000 65 63 68 6f 20 22 74 65 73 74 69 6e 67 22 0a 73 |echo "testing".s|\n00000010 74 61 74 20 2e 0a 65 63 68 6f 20 22 74 65 73 74 |tat ..echo "test|\n00000020 69 6e 67 20 61 67 61 69 6e 22 0a |ing again".|\n0000002b\nRun Code Online (Sandbox Code Playgroud)\n\n...然后,原则上,可以在 Ubuntu 上运行它,这似乎在这种情况下有效:
\n\n$ dos2unix <tmp.sh | bash\ntesting\n File: .\n Size: 20480 Blocks: 40 IO Block: 4096 directory\nDevice: 816h/2070d Inode: 1572865 Links: 27\nAccess: (1777/drwxrwxrwt) Uid: ( 0/ root) Gid: ( 0/ root)\nAccess: 2020-04-03 11:11:00.309160050 +0200\nModify: 2020-04-03 11:10:58.349139481 +0200\nChange: 2020-04-03 11:10:58.349139481 +0200\n Birth: -\ntesting again\nRun Code Online (Sandbox Code Playgroud)\n\n然而,除了需要记住的稍微混乱的命令之外,这也改变了 bash 语义,因为 stdin 不再是终端;这可能适用于这个简单的示例,但请参阅/sf/ask/1628007321/作为更大问题的示例。
\n据我所知,xe2x80x99m 没有办法告诉 Bash 接受 Windows 风格的行结尾。
\n\n在涉及 Windows 的情况下,常见的做法是依靠 Git\xe2\x80\x99s 在提交时使用autocrlf配置标志自动转换行结束符的能力。例如,请参阅有关行结尾的 GitHub\xe2\x80\x99s 文档,该文档不是 GitHub 特有的\xe2\x80\x99s。这样,文件就会在存储库中以 Unix 风格的行结尾提交,并根据每个客户端平台进行适当的转换。
(相反的问题是 \xe2\x80\x99t 问题:MSYS2 在 Windows 上可以很好地处理 Unix 风格的行结尾。)
\n| 归档时间: |
|
| 查看次数: |
18977 次 |
| 最近记录: |