在 Windows 上编辑的 Bash/Korn shell 脚本抛出错误“...^M: not found”

Ken*_*war 10 bash editors ksh character-encoding windows

我使用 Notepad++ 在 Windows 中编写了一个 Bash 脚本。

cxStopAllServicesOnSERVER.sh

#!/usr/bin/bash
cd "/some/path"
echo "Hi. Logs can be found at "`pwd`"/cxStartStopLogger.log"
echo "["`date`"]*** STOPPING ALL SERVICES ON SERVER ***" >> "cxStartStopLogger.log"
exit
Run Code Online (Sandbox Code Playgroud)

现在上传并设置所需的文件权限后,我尝试按如下方式执行它:

bash-3.00$ cat cxStopAllServicesOnSERVER.sh #Let's have a look at the code.
#!/usr/bin/bash
cd "/some/path/"
echo "Hi. Logs can be found at "`pwd`"/cxStartStopLogger.log"
echo "["`date`"]*** STOPPING ALL SERVICES ON SERVER ***" >> "cxStartStopLogger.log"

bash-3.00$ # Code and hashbang 'looks' correct, 
bash-3.00$ # if there is any issue with the format (EOL characters and such) 
bash-3.00$ # we cannot see it using cat.
bash-3.00$ 
bash-3.00$ sh cxStopAllServicesOnSERVER.sh
cxStopAllServicesOnSERVER.sh[2]: /some/path^M:  not found
Hi. Logs can be found at /some/path/cxStartStopLogger.log
bash-3.00$ # Note that ^M appears at the end of the line.

bash-3.00$ bash -x cxStopAllServicesOnSERVER.sh
+ cd $'/some/path\r'
: No such file or directory1.sh: line 2: cd: /some/path
++ pwd
' echo 'Hi. Logs can be found at /some/path/cxStartStopLogger.log
Hi. Logs can be found at /some/path/cxStartStopLogger.log
++ date
+ echo '[Sun' Nov 18 00:28:17 EST '2012]*** STOPPING ALL SERVICES ON SERVER ***'
bash-3.00$ # Note that '\r' return character appears at the end of the line.
Run Code Online (Sandbox Code Playgroud)

问题: 当我将代码更改为 korn shell 时,我面临同样的问题。似乎在行尾添加了不正确的字符。

注意: 我找到了解决方案并发布了与答案相同的内容。随时更新或改进它以帮助可能面临相同问题的其他初学者。谢谢!

Ken*_*war 17

在窥探了各种论坛和一些 Stack-overflow 帖子后,我发现了这个问题。

这里有一个解释,可以更好地理解和“看到”错误的根本原因。

首先,如果您在 Windows 上编写代码,最好用 Notepad++ 武装自己。在我看来,它基本上是文本编辑器的瑞士军刀。

现在要查看 EOL(行尾)字符和其他控制符号,请执行以下操作:

1. 在 Notepad++ 中打开文件。

从菜单栏中选择查看 > 显示符号 > 显示所有字符

您现在应该看到如下符号: Notepad++ 的屏幕截图:在 Windows 上编辑 UNIX 脚本

啊哈!Windows/MS-DOS 使用 CR+LF 来指示行尾。现在 UNIX 使用 LF 字符来表示行终止(EOL 字符)。

2.1.让我们将 Windows EOL 转换为 UNIX EOL:

选择编辑 > EOL 转换 > UNIX 格式

您应该会看到如下内容:

Notepad++:EOL 转换为 UNIX 格式的屏幕截图 这解释了为什么我们看到 '\r' 字符被附加到行尾。这是因为 UNIX 将 '\n' 或 LF(换行符)识别为行终止符/EOL 字符,但忽略了 '\r' 或 ^M(回车符)字符。

我们还可以通过以下方式测试 EOL 问题

bash-3.00$ head myScript.sh | cat -vet | head -1
#usr/bin/bash^M$
bash-3.00$ #We see that ^M, that is \r is found at the end of each line. 
Run Code Online (Sandbox Code Playgroud)

2.2.如果您想在 UNIX 上将文件从 Windows 转换为 UNIX EOL 格式,则有两种方法可以解决此问题:

$ dos2unix myScript.sh
Run Code Online (Sandbox Code Playgroud)

或者

使用@Chris Down提供的解决方案如下:

$ sed -i 's/\r$//' myScript.sh
Run Code Online (Sandbox Code Playgroud)

参考:

  1. 有关线路终止r-and-n 之间的差异是什么的更多信息,请参阅这些链接。

  • 优秀的答案!我认为对于坚持使用 `pico` 的小问题,命令行编辑器应该是解决方案。 (2认同)