我正在Mac上制作一个NW.js应用程序,希望通过双击图标在开发模式下运行该应用程序。第一步,我要让我的shell脚本工作
在Windows上使用VSCode(我想争取时间),我在项目的根目录下创建了一个run-nw
文件,其中包含以下内容:
#!/bin/bash
cd "src"
npm install
cd ..
./tools/nwjs-sdk-v0.17.3-osx-x64/nwjs.app/Contents/MacOS/nwjs "src" &
但我得到的结果是:
$ sh ./run-nw
: command not found
: No such file or directory
: command not found
: No such file or directory
Usage: npm <command>
where <command> is one of: (snip commands list)
(snip npm help)
npm@3.10.3 /usr/local/lib/node_modules/npm
: command not found
: No such file or directory
: command not found
我真的不明白:
\n
替换\r\n
(以防\r
产生问题),但它没有改变任何东西李>dirname
指令),或者它不知道cd
命令李>npm
的install
参数npm install
)李>由于无法使其正常工作,并且怀疑文件本身有什么奇怪的地方,我直接在Mac上创建了一个新文件,这次使用的是vim。我输入了完全相同的指令,然后。。。现在它可以正常工作了。
两个文件上的差异显示完全没有差异
有什么区别?什么会使第一个脚本不起作用?我怎么知道
按照公认答案的建议,在返回错误的行尾后,我检查了多项内容。事实证明,由于我从Windows机器复制了~/.gitconfig
,所以我有autocrlf=true
,所以每次我在Windows下修改bash文件时,它都会将行结尾重新设置为\r\n
。
因此,除了运行dos2unix
(您必须在Mac上使用自制软件安装),如果您使用的是Git,请检查您的配置
如果使用
read
命令读取DOS/Windows格式的文件(或管道)(或可能是),则可以利用read
将从行首和行尾修剪空白的事实。如果您告诉它回车是空格(通过将它们添加到IFS
变量中),它将从行的末尾修剪它们在bash(或zsh或ksh)中,这意味着您将替换以下标准习惯用法:
为此:
(注意:
-r
选项与此无关,它只是一个避免弄乱反斜杠的好主意。)如果您没有使用
IFS=
前缀(例如,因为您想将数据拆分为字段),那么您应该替换此前缀:为此:
如果您使用的shell不支持
$'...'
引用模式(例如,dash,某些Linux发行版上的默认/bin/sh),或者您的脚本甚至可能使用这种shell运行,那么您需要稍微复杂一些:请注意,通常情况下,当您更改
IFS
时,应尽快将其恢复正常,以避免奇怪的副作用;但在所有这些情况下,它都是read
命令的前缀,因此它只影响一个命令,不必在之后重置对。Bash脚本对行结尾非常敏感,无论是在脚本本身还是在它处理的数据中。它们应该有Unix风格的行尾,即每一行都以换行字符(十进制10,ASCII中的十六进制0A)结尾
脚本中的DOS/Windows行结尾
对于Windows或DOS样式的行尾,每行都以回车符结尾,后跟换行符。您可以在
cat -v yourfile
的输出中看到这个不可见的字符:在这种情况下,回车(
^M
在插入符号中或\r
在C转义符号中)不被视为空白。Bash将shebang后面的第一行(由单个回车符组成)解释为要运行的命令/程序的名称^M
的命令,它将打印: command not found
"src"^M
(或src^M
)的目录,它将打印: No such file or directory
install^M
而不是install
作为参数传递给npm
,从而导致npm
投诉李>输入数据中的DOS/Windows行结束符
如上所述,如果您有一个带有回车符的输入文件:
然后,在编辑器中以及在将其写入屏幕时,它将看起来完全正常,但工具可能会产生奇怪的结果。例如,
grep
将无法找到明显存在的行:追加的文本将覆盖该行,因为回车符会将光标移动到该行的开头:
字符串比较似乎会失败,即使写入屏幕时字符串看起来相同:
解决方案
解决方案是将文件转换为使用Unix样式的行尾。实现这一点的方法有很多:
这可以使用
dos2unix
程序完成:在具有功能的文本编辑器(Sublime,Notepad++,而不是Notepad)中打开文件,并将其配置为使用Unix行结尾保存文件,例如使用Vim,在(重新)保存之前运行以下命令:
如果您有一个版本的
sed
实用程序支持-i
或--in-place
选项,例如GNUsed
,则可以运行以下命令来剥离尾部回车:对于其他版本的
sed
,可以使用输出重定向写入新文件。确保重定向目标使用不同的文件名(以后可以重命名)类似地,
tr
翻译过滤器可用于从输入中删除不需要的字符:Cygwin Bash
对于Cygwin的Bash端口,有一个自定义的
igncr
选项,可以设置为忽略行结尾中的回车(可能是因为它的许多用户使用本机Windows程序编辑文本文件)。 这可以通过运行set -o igncr
为当前shell启用设置此选项仅适用于当前shell进程,因此在查找包含无关回车的文件时,此选项非常有用。如果您经常遇到具有DOS行结尾的shell脚本,并且希望永久设置此选项,则可以将名为
SHELLOPTS
(所有大写字母)的环境变量设置为包含igncr
。Bash使用此环境变量在启动时(在读取任何启动文件之前)设置shell选项实用工具
file
实用程序可用于快速查看文本文件中使用了哪些行尾。以下是它为每种文件类型打印的内容:Bourne-Again shell script, ASCII text executable
Bourne-Again shell script, ASCII text executable, with CR line terminators
Bourne-Again shell script, ASCII text executable, with CRLF line terminators
GNU版本的
cat
实用程序有一个-v, --show-nonprinting
选项,用于显示非打印字符dos2unix
实用程序是专门为在Unix、Mac和D之间转换文本文件而编写的OS行结束符有用的链接
维基百科有一个excellent article涵盖了标记一行文本结尾的许多不同方式、此类编码的历史以及在不同操作系统、编程语言和互联网协议(如FTP)中如何处理新行
具有经典Mac OS行结尾的文件
对于Classic Mac OS(OSX之前),每一行都以回车符终止(十进制13,ASCII中的十六进制0D)。如果脚本文件以这样的行结尾保存,Bash将只看到一行长的行,如下所示:
由于这一行以octothorpe(
#
)开头,Bash将这一行(以及整个文件)视为一条注释注:2001年,苹果推出了基于BSD衍生的NeXTSTEP操作系统的MacOSX。因此,OSX也使用Unix风格的LF-only行结尾,从那时起,以CR结尾的文本文件变得极为罕见。尽管如此,我认为值得展示Bash如何尝试解释这些文件
在JetBrains产品(PyCharm、PHPStorm、IDEA等)上,您需要单击
CRLF
/LF
上的,以在两种类型的行分隔符(\r\n
和\n
)之间切换相关问题 更多 >
编程相关推荐