代码之家  ›  专栏  ›  技术社区  ›  moongdal

为什么addgroup说我的名字以破折号开头?[重复]

  •  0
  • moongdal  · 技术社区  · 3 年前

    我在打电话。在Mac上运行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
    

    我真的不明白:

    • 它似乎以空行作为命令。在我的编辑器(VSCode)中,我试图替换 \r\n 具有 \n (如果 \r 制造问题),但它不会改变任何事情。
    • 它似乎找不到文件夹(带或不带 dirname 或者它不知道 cd 命令
    • 它似乎不明白 install 争论 npm
    • 真正让我感到奇怪的是,它仍然在运行应用程序(如果我做了一个测试) npm install 手动)。。。

    由于无法使其正常工作,并且怀疑文件本身有什么奇怪的地方,我直接在Mac上创建了一个新文件,这次使用的是vim。我输入了完全相同的指令,然后。。。现在它可以正常工作了。
    两个文件的差异显示完全没有差异。

    有什么区别?什么会让第一个脚本不起作用?我怎么知道?

    使现代化

    按照公认答案的建议,在错误的行尾出现后,我检查了多项内容。事实证明,自从我复制了我的 ~/.gitconfig 在我的Windows电脑上,我 autocrlf=true ,所以每次我在Windows下修改bash文件时,它都会将行尾重新设置为 \r\n .
    所以,除了跑步 dos2unix (必须在Mac上使用自制软件安装),如果使用Git,请检查配置。

    0 回复  |  直到 3 年前
        1
  •  0
  •   Leandro Bardelli    2 年前

    对Bash脚本 对行尾敏感,无论是在脚本本身还是它处理的数据中。它们应该有Unix风格的行尾,即每一行都以换行字符(十进制10,ASCII中的十六进制0A)结尾。

    脚本中的DOS/Windows行结尾

    对于Windows或DOS样式的行尾,每行都以回车符结尾,后跟换行符。您可以在的输出中看到这个不可见的字符 cat -v yourfile :

    $ cat -v yourfile
    #!/bin/bash^M
    ^M
    cd "src"^M
    npm install^M
    ^M
    cd ..^M
    ./tools/nwjs-sdk-v0.17.3-osx-x64/nwjs.app/Contents/MacOS/nwjs "src" &^M
    

    在这种情况下,马车返回( ^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行结束符

    如上所述,如果您有一个带有回车符的输入文件:

    hello^M
    world^M
    

    然后,在编辑器中以及在将其写入屏幕时,它将看起来完全正常,但工具可能会产生奇怪的结果。例如 grep 将无法找到明显存在的行:

    $ grep 'hello$' file.txt || grep -x "hello" file.txt
    (no match because the line actually ends in ^M)
    

    附加文本将覆盖行,因为回车符会将光标移到行的开头:

    $ sed -e 's/$/!/' file.txt
    !ello
    !orld
    

    字符串比较似乎会失败,即使在写入屏幕时字符串似乎相同:

    $ a="hello"; read b < file.txt
    $ if [[ "$a" = "$b" ]]
      then echo "Variables are equal."
      else echo "Sorry, $a is not equal to $b"
      fi
    
    Sorry, hello is not equal to hello
    

    解决

    解决方案是将文件转换为使用Unix样式的行尾。有很多方法可以实现这一点:

    1. 这可以使用 dos2unix 节目:

      dos2unix filename
      
    2. 在一个文件夹中打开文件 有能力 文本编辑器(Supreme、Notepad++,而不是Notepad)并将其配置为使用Unix行结尾保存文件(例如,使用Vim),在(重新)保存之前运行以下命令:

      :set fileformat=unix
      
    3. 如果你有一个版本的 sed 支持 -i --in-place 选项,例如GNU 塞德 ,可以运行以下命令来剥离尾部回车:

      sed -i 's/\r$//' filename
      

      与其他版本的 塞德 ,可以使用输出重定向写入新文件。确保重定向目标使用不同的文件名(以后可以重命名)。

      sed 's/\r$//' filename > filename.unix
      
    4. 同样地 tr 翻译过滤器可用于从输入中删除不需要的字符:

      tr -d '\r' <filename >filename.unix
      

    辛格温·巴什

    对于Cygwin的Bash端口,有一个定制 igncr 选项,可以设置为忽略行尾中的回车符(可能是因为许多用户使用本机Windows程序编辑文本文件)。 这可以为 现在的 跑步脱壳 set -o igncr .

    设置此选项仅适用于 现在的 shell过程,以便在 采购 包含无关运输申报的文件。如果您经常遇到带有DOS行结尾的shell脚本,并且希望永久设置此选项,则可以设置一个名为 SHELLOPTS (所有大写字母)包括 igncr 。Bash使用此环境变量在启动时(在读取任何启动文件之前)设置shell选项。

    实用工具

    这个 file 该实用程序可用于快速查看文本文件中使用的行尾。以下是它为每种文件类型打印的内容:

    • Unix行结尾: Bourne-Again shell script, ASCII text executable
    • Mac行结尾: Bourne-Again shell script, ASCII text executable, with CR line terminators
    • DOS行结尾: Bourne-Again shell script, ASCII text executable, with CRLF line terminators

    GNU版本的 cat 公用事业公司有一个 -v, --show-nonprinting 显示非打印字符的选项。

    这个 dos2unix 该实用程序专门用于在Unix、Mac和DOS行尾之间转换文本文件。

    有用的链接

    维基百科有一个 excellent article 涵盖了标记一行文本结尾的多种不同方式,此类编码的历史,以及在不同操作系统、编程语言和互联网协议(如FTP)中如何处理新行。

    带有经典Mac OS行结尾的文件

    具有 Classic Mac OS (在OS X之前),每一行都以回车符终止(十进制13,ASCII中的十六进制0D)。如果脚本文件以这样的行结尾保存,Bash只会看到一行这样的长行:

    #!/bin/bash^M^Mcd "src"^Mnpm install^M^Mcd ..^M./tools/nwjs-sdk-v0.17.3-osx-x64/nwjs.app/Contents/MacOS/nwjs "src" &^M
    

    因为这条长长的线是从一只章鱼开始的( #

    注:2001年,苹果推出了基于BSD的Mac OS X NeXTSTEP 操作系统。因此,OS X也使用Unix风格的LF-only行结尾,从那时起,以CR结尾的文本文件变得极为罕见。尽管如此,我认为有必要展示Bash将如何解释这些文件。