Shell 脚本在使用 nano 保存时有效,但在使用 Notepad++ 保存时无效

use*_*938 4 windows shell-script newlines

当我将我的 bash 脚本从 Notepad++ 复制到一个带有 nano 编辑器的新文件中并保存时。它运行良好。(sh ./安装)。

但是如果我保存文件(完全相同的内容),上传到我的网络服务器,在同一台机器上使用 Wget 下载它。我收到语法错误。我检查了编码,它们似乎是一样的。从那以后,我使用了大量的字符编码来查看它是否能解决问题。使用 wget 下载文件后,我还将文件设置为可执行文件!

该文件运行良好,使用 nano 复制和粘贴时我的错误为零。知道这可能是什么吗?

ter*_*don 8

我愿意打赌这个问题与行尾有关。您可能正在沿线某处使用非 *nix 机器。我还遇到了一个问题apache(在 Linux 上运行)向上传的文本文件添加 Windows 样式的行尾,因此您可能会看到类似的内容。

要进行测试,请获取您下载的文件并通过od. 如果它是一个长文件,只需抓取前几行:

head script.sh | od -c
Run Code Online (Sandbox Code Playgroud)

查看输出并检查您是否有以下内容:

f   o   o  \r  \n
Run Code Online (Sandbox Code Playgroud)

\r是一个回车,在 Windows 上,行以与*nix\r\n相对的结尾\n。如果事实证明这确实是问题所在,您可以通过删除回车符来修复您的文件:

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

  • 优秀的答案!我要补充一点,它在粘贴到编辑器时起作用的原因是,通过 SSH shell 发出的回车将存储为 Unix 行尾——这就是为什么它在剪切和粘贴时起作用,但在原始文件时不起作用被 scp 或 ftp 结束了。 (2认同)

slm*_*slm 5

正如@graeme 敏锐地指出的那样,因为您在服务器上都有两种形式的脚本,您可以执行一个简单的操作diff来确定工作版本和有问题的版本之间有什么不同。

$ diff working.sh broken.sh
Run Code Online (Sandbox Code Playgroud)

你也可以像这样并排比较:

$ diff -y working.sh broken.sh
Run Code Online (Sandbox Code Playgroud)

如果脚本由于某种拼写错误而无法运行,您通常可以通过将-x开关添加到来检测这些问题bash,这会导致它变得冗长。

$ bash -x broken.sh
Run Code Online (Sandbox Code Playgroud)

您还可以将此开关合并到#!/bin/bash脚本顶部的 shebang ( ) 中,如下所示:

#!/bin/bash -x
Run Code Online (Sandbox Code Playgroud)

行尾

这通常是将文件从 Windows 移动到 Unix/Linux 系统时的问题。问题与如何在 2 个平台上表示行的末端有关。您可以在 Wikipedia 上阅读更多相关信息,标题为:换行符

制作示例文件

$ echo -e "This is a file.\nThat I made on Unix.\n" > unixfile.txt
Run Code Online (Sandbox Code Playgroud)

正如@terdon 在他的回答中所描述的那样,您可以使用sed来去除这些内容,您也可以经常使用一个名为的工具dos2unix来做同样的事情。您可以通过以下两种方式之一使用它:

$ dos2unix unixfile.txt
Run Code Online (Sandbox Code Playgroud)

或者如果您不想覆盖现有文件:

$ dos2unix -n oldfile.txt newfile.txt
Run Code Online (Sandbox Code Playgroud)

当您使用diff我之前提到的上述内容时,当您比较这两个文件时,您会得到这样的输出:

$ diff -y unixfile.txt winfile.txt 
This is a couple                            |   This is a couple
of lines of sample                          |   of lines of sample
text.                                       |   text.
Run Code Online (Sandbox Code Playgroud)

您将无法辨别差异,只是它们就在那里。@terdon 的回答再次显示了一种使用od. 您当然可以使用多种方法来弄清楚发生了什么。

使用 vim

filecmd。

$ file unixfile.txt
winfile.txt: ASCII text 

$ file winfile.txt 
unixfile.txt: ASCII text, with CRLF line terminators
Run Code Online (Sandbox Code Playgroud)

上面强调了一个问题,即来自 Windows 的文件具有 CRLF(也就是行尾的回车符 + 换行符)。这些字符是十六进制的 0x0D 和 0x0A,如果您想了解更多信息,请再次参阅维基百科关于换行符的文章

您也可以使用vim来查看问题:

$ vim winfile.txt
Run Code Online (Sandbox Code Playgroud)

这是一个小序列,显示了如何vim查看问题。CRLF 字符在 Unix 中通常显示为^M,即Ctrl+ M

                                       vim的ss

该序列显示我重新打开文件,winfile.txt作为格式化的 Unix 文件 ( :e ++ff=unix)。这告诉vim不要自动检测文件是否为 Windows 格式化,因此它将显示^M行终止字符。