各种 shell 中的反斜杠、反引号和插入符有何意义

use*_*531 3 shell powershell command-prompt docker line-continuation

我在 Windows PC 上关注https://docs.docker.com/get-started/06_bind_mounts/#start-a-dev-mode-container并卡在这里:

\n
\n

运行以下命令。我们\xe2\x80\x99稍后会解释\xe2\x80\x99发生了什么:

\n
\n
 docker run -dp 3000:3000 \\\n     -w /app -v "$(pwd):/app" \\\n     node:12-alpine \\\n     sh -c "yarn install && yarn run dev"\n
Run Code Online (Sandbox Code Playgroud)\n
\n

如果您使用的是 PowerShell,请使用以下命令:

\n
\n
 docker run -dp 3000:3000 `\n     -w /app -v "$(pwd):/app" `\n     node:12-alpine `\n     sh -c "yarn install && yarn run dev"\n
Run Code Online (Sandbox Code Playgroud)\n

使用命令提示符时,我收到错误(尝试了多种变体,如下所示),而使用 PowerShell 时,我似乎没有收到错误,但没有运行任何内容,如执行时所示docker ps。\n请注意,我宁愿使用命令提示符而不是 PowerShell,因为我可以在 PC 上通过 ComandPrompt 使用 Linux 命令。

\n

在命令提示符下使用 Docker(以及与 PowerShell 相关的刻度线)时,反斜杠有何意义?

\n

我发现它的docker run -dp 3000:3000 -w /app -v "%cd%:/app" node:12-alpine sh -c "yarn install && yarn run dev"工作没有错误(去掉反斜杠,放在一行,并使用%cd%而不是$(pwd)),但仍然想知道为什么在示例中使用确切的脚本会导致错误。

\n

使用命令提示符

\n
C:\\Users\\michael\\Documents\\Docker\\app>docker run -dp 3000:3000 \\\ndocker: invalid reference format.\nSee \'docker run --help\'.\n\nC:\\Users\\michael\\Documents\\Docker\\app>     -w /app -v "$(pwd):/app" \\\n\'-w\' is not recognized as an internal or external command,\noperable program or batch file.\n\nC:\\Users\\michael\\Documents\\Docker\\app>     node:12-alpine \\\nThe filename, directory name, or volume label syntax is incorrect.\n\nC:\\Users\\michael\\Documents\\Docker\\app>     sh -c "yarn install && yarn run dev"\nsh: yarn: command not found\n\nC:\\Users\\michael\\Documents\\Docker\\app>docker run -dp 3000:3000 \\ -w /app -v "$(pwd):/app" \\ node:12-alpine \\ sh -c "yarn install && yarn run dev"\ndocker: invalid reference format.\nSee \'docker run --help\'.\n\nC:\\Users\\michael\\Documents\\Docker\\app>docker run -dp 3000:3000 -w /app -v "$(pwd):/app" node:12-alpine sh -c "yarn install && yarn run dev"\ndocker: Error response from daemon: create $(pwd): "$(pwd)" includes invalid characters for a local volume name, only "[a-zA-Z0-9][a-zA-Z0-9_.-]" are allowed. If you intended to pass a host directory, use absolute path.\nSee \'docker run --help\'.\n\nC:\\Users\\michael\\Documents\\Docker\\app>\n
Run Code Online (Sandbox Code Playgroud)\n

使用PowerShell

\n
PS C:\\Users\\michael\\Documents\\Docker>  docker run -dp 3000:3000 `\n>>      -w /app -v "$(pwd):/app" `\n>>      node:12-alpine `\n>>      sh -c "yarn install && yarn run dev"\n849af42e78d4ab09242fdd6c3d03bcf1b6b58de984c4485a441a2e2c88603767\nPS C:\\Users\\michael\\Documents\\Docker> docker ps\nCONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES\nPS C:\\Users\\michael\\Documents\\Docker>\n
Run Code Online (Sandbox Code Playgroud)\n

mkl*_*nt0 10

\n

仍然想知道为什么在示例中使用确切的脚本会导致错误。

\n
\n

因为带有行结束字符的命令\\适用于POSIX 兼容的 shell,例如bash,而不是cmd.exe

\n
    \n
  • POSIX 兼容 shell ( sh, bash, dash, ksh, zsh):

    \n
      \n
    • 一般用于\\行继续(在下一行继续命令)和转义。
    • \n
    • 用于$varName引用环境变量和仅 shell 变量。
    • \n
    • 支持在命令行中$(...)嵌入命令 () 的输出(命令替换)。...
    • \n
    • 支持双引号("...",插值)和单引号(\'...\',逐字)字符串;使用\'\\\'\'- 实际上 - 包含一个\'inside \'...\'
      \n(此外,在bashksh、 和 中zsh,有很少使用的ANSI C 引用字符串、$\'...\'、 和,在bash和 中ksh,也许更罕见的是可本地化字符串, $"...")。
    • \n
    \n
  • \n
  • cmd.exe

    \n
      \n
    • ^一般用于续行和转义(仅在不带引号的参数中)。
    • \n
    • 用于%varName%引用环境变量(唯一支持的变量类型)。
    • \n
    • 根本不支持命令替换。
    • \n
    • 仅支持"..."字符串(插值)。
    • \n
    \n
  • \n
  • 电源外壳

    \n
      \n
    • `一般使用(反引号)进行续行和转义。
    • \n
    • 用于$env:varName引用环境变量、$varName引用仅 shell 变量。
    • \n
    • 支持$(...),称为子表达式,相当于命令替换(在双引号字符串之外,(...)通常就足够了)。
    • \n
    • 支持双引号("...",插值)和单引号(\'...\',逐字)字符串;用于\'\'嵌入一个\'内部\'...\'.
    • \n
    • 注意:一个常见的陷阱是,与 POSIX 兼容的 shell 和 相比, PowerShell 具有更多的元字符cmd.exe,特别是包括@ { } , ;,因此需要`在未加引号的参数中进行单独转义或在加引号的字符串中嵌入 - 请参阅此答案
    • \n
    \n
  • \n
\n

潜在的行延续陷阱:在讨论的所有 shell 中,转义字符必须是行中的最后一个字符- 甚至不允许尾随(行内)空白(因为转义字符将应用于而不是换行符)。

\n

上述信息总结如下表:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
特征POSIX shell\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0 \xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0_cmd.exe\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\ xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0_PowerShell\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\ xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0\xc2\xa0_
续行符/转义符反斜杠 ( \\)插入符 ( ^)反引号 ( `)
双引号字符串(插值)\xe2\x9c\x85\xe2\x9c\x85\xe2\x9c\x85
单引号字符串(逐字)\xe2\x9c\x85\xe2\x9d\x8c\xe2\x9c\x85
获取/设置环境变量$varName/
export varName=...
%varName%/
set varName=...
$env:varName/
$env:varName = ...
获取/设置仅 shell 变量$varName/
varName=...
\xe2\x9d\x8c (不存在此类变量,但您可以使用 限制 env.vars. 的范围setlocal$varName/
$varName = ...
命令替换、子表达式$(...)\xe2\x9d\x8c(...)/ $(...),特别是。在字符串中
\n
\n

请注意根据符号两侧的空格重新设置变量=

\n
    \n
  • 在类似 POSIX 的 shell 中,周围不能有空格=
  • \n
  • 在 中cmd.exe,此类空格很重要,并且成为变量/值名称的一部分,因此通常要避免
  • \n
  • 在 PowerShell 中,此类空格是可选的- 您可以使用它来增强可读性;任何要分配的字符串值都需要引号(例如,$var = \'hi!\'
  • \n
\n

也可以看看:

\n\n

  • 非常全面和高质量的答案。考虑到搜索这些类型的项目的信息很困难,特别有帮助。谢谢。 (3认同)