能够将 `\r` 视为空白字符的 Shell

Gre*_*bet 7 cygwin newlines

作为一个个人项目,我正在尝试编写一个脚本来清理在 Cygwin 下运行的 Windows 10 附带的一些无关文件。我希望脚本能够复制和粘贴,这需要它对不同类型的换行符具有健壮性。是否有任何类似shshell 可以将处理\r为空格的能力,可能是在设置了某些选项时?

这是一件奇怪的事情。答案可能归结为“是的,这是一件奇怪的事情,没有办法做到”。

Mic*_*mer 7

通常,这对于实际脚本是不可能的。

  1. 一个独立的可执行脚本将有一个 shebang 行来标识要使用的解释器:

    #!/bin/sh
    
    Run Code Online (Sandbox Code Playgroud)

    问题是,无论解释器如何,shebang 行本身都会在结尾之前包含一个回车符,这意味着不会找到解释器(除非字面上不太可能的可执行名称$'sh\r'- 我认为这在 Windows 上是非法的) .

  2. 另一种可执行脚本是设置了执行位的纯文本文件,POSIX 需要将其解释为 POSIX shell 命令语言中的脚本(当从兼容 shell 本身调用时)。但是,正如您所发现的,这种 shell 语言将回车符视为数据字节,因此您遇到了已确定的问题。


你有一些选择。一种是直接放弃实际的可执行脚本,并简单地先调用其他语言的解释器。您已经确定了 Perl 和 Python,事实上,大多数脚本语言都对任何现代行尾格式感到满意。调用脚本 asperl cleanup.pl不会有问题。

然而,在传统的 shell 语言中,许多管理任务要容易得多,而且还有一个技巧:用注释结束每一行。

echo hello #
rm file.ext #
mv /path/other.fl /path/bin #
Run Code Online (Sandbox Code Playgroud)

#字符在所有标准 shell 中(在非交互式上下文中)的行尾引入注释。注释将包括回车字节,这是注释的一个很好的元素,然后立即以终止换行字节结束。

在散列之前有一个空格很重要:#单词内的 a不是注释的开头,而是单词 的一部分

您可以使用 shell 直接运行此脚本:

bash cleanup.sh
dash cleanup.sh
sh cleanup.sh
Run Code Online (Sandbox Code Playgroud)

但是,如果您要通过从现有的 shell 会话中键入命令来启动它,那么前面提到的那些 POSIX 脚本也将起作用:只需使文件可执行,然后

./cleanup.sh
Run Code Online (Sandbox Code Playgroud)

将使用您的 shell 认为对 POSIX 脚本执行正确的任何操作来运行它。

由于这听起来像是一次性的,因此可能不值得付出努力使其可执行,所以sh cleanup.sh对我来说似乎足够了。


我对这种情况的诚实建议可能是 Powershell(或批量推送),但我知道这不是您想要的。WSL 是另一种选择:它会自动处理 shebang 行中的回车,然后您可以使用注释处理其余部分。