各种 shell 中反斜杠、反引号和插入符号的意义是什么

What is the significance of backslashes, backticks, and carets in various shells

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

Run the following command. We’ll explain what’s going on afterwards:

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

If you are using PowerShell then use this command:

 docker run -dp 3000:3000 `
     -w /app -v "$(pwd):/app" `
     node:12-alpine `
     sh -c "yarn install && yarn run dev"

使用命令提示符时出现错误(尝试了多种变体,如下所示),使用 PowerShell 时似乎没有出现错误,但 运行 执行 docker ps。 请注意,我宁愿使用命令提示符而不是 PowerShell,因为我可以在我的 PC 上使用 Linux 命令和 ComandPrompt。

在命令提示符下使用 Dockers 时反斜杠的意义是什么(以及与 PowerShell 相关的刻度线)?

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

使用命令提示符

C:\Users\michael\Documents\Docker\app>docker run -dp 3000:3000 \
docker: invalid reference format.
See 'docker run --help'.

C:\Users\michael\Documents\Docker\app>     -w /app -v "$(pwd):/app" \
'-w' is not recognized as an internal or external command,
operable program or batch file.

C:\Users\michael\Documents\Docker\app>     node:12-alpine \
The filename, directory name, or volume label syntax is incorrect.

C:\Users\michael\Documents\Docker\app>     sh -c "yarn install && yarn run dev"
sh: yarn: command not found

C:\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"
docker: invalid reference format.
See 'docker run --help'.

C:\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"
docker: 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.
See 'docker run --help'.

C:\Users\michael\Documents\Docker\app>

使用 PowerShell

PS C:\Users\michael\Documents\Docker>  docker run -dp 3000:3000 `
>>      -w /app -v "$(pwd):/app" `
>>      node:12-alpine `
>>      sh -c "yarn install && yarn run dev"
849af42e78d4ab09242fdd6c3d03bcf1b6b58de984c4485a441a2e2c88603767
PS C:\Users\michael\Documents\Docker> docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
PS C:\Users\michael\Documents\Docker>

这是字符转义。

X 字符(Bash 的 \,Powershell 的反引号和 Windows 终端的 ^ )用于删除下一个字符的任何特定含义。

当用在行尾时,这意味着下一个字符(换行符)将被完全忽略。

从解释器的角度来看,这使命令本质上是一个单行命令,但允许您将其分成多行以提高可读性。

参考资料

Powershell - About special characters

Escape sequences begin with the backtick character [`], known as the grave accent (ASCII 96), and are case-sensitive. The backtick character can also be referred to as the escape character.

Bash manual

3.1.2.1 转义字符

A non-quoted backslash \ is the Bash escape character. It preserves the literal value of the next character that follows, with the exception of newline. If a \newline pair appears, and the backslash itself is not quoted, the \newline is treated as a line continuation (that is, it is removed from the input stream and effectively ignored).

How-to: Escape Characters, Delimiters and Quotes at the Windows command line

Escaping CR/LF line endings. The ^ escape character can be used to make long commands more readable by splitting them into multiple lines and escaping the Carriage Return + Line Feed (CR/LF) at the end of a line:

ROBOCOPY \FileServ1\e$\users ^
\FileServ2\e$\BackupUsers ^
/COPYALL /B /SEC /MIR ^
/R:0 /W:0 /LOG:MyLogfile.txt /NFL /NDL

[...]

A couple of things to be aware of:

A stray space at the end of a line (after the ^) will break the command, this can be hard to spot unless you have a text editor that displays spaces and tab characters. If you want comment something out with REM, then EVERY line needs to be prefixed with REM. Alternatively if you use a double colon :: as a REM comment, that will still parse the caret at the end of a line, so in the example above changing the first line to :: ROBOCOPY… will comment out the whole multi-line command.

would still like to know why using the exact script in the example results in errors.

因为 带有行尾 \ 字符的命令适用于 POSIX 兼容的 shells 例如bash,不适用于cmd.exe

  • POSIX兼容shells (sh, bash, dash, ksh, zsh):

    • 使用\ 进行续行(在下一行继续一个命令)和转义。
    • 使用 $varName 来引用环境变量和 shell-only 变量。
    • 支持 $(...) 在命令行(命令替换)中嵌入命令(...)的输出。
    • 支持双引号("...",插值)和单引号('...',逐字)字符串;使用 '\'' - 实际上 - 在 '...'.
      中包含一个 ' (此外,在bashkshzsh中,还有很少使用的ANSI C-quoted strings, $'...', and, in bash and ksh, perhaps even more rarely, localizable strings$"...")。
  • cmd.exe:

    • 一般使用 ^ 进行续行和转义(仅在未加引号的参数中)。
    • 使用%varName%引用环境变量(唯一支持的变量类型)。
    • 根本不支持命令替换。
    • 仅支持 "..." 个字符串(内插)。
  • PowerShell:

    • 通常使用 `(反引号)进行续行和转义。
    • 使用 $env:varName 引用环境变量,$varName 引用 shell-only 变量。
    • 支持 $(...),称为 子表达式 ,相当于命令替换(双引号字符串之外,(...) 通常就足够了)。
    • 支持双引号("...",插值)和单引号('...',逐字)字符串;使用 '''...'.
    • 中嵌入一个 '
    • 注意:一个常见的陷阱是 PowerShell 有更多 metacharacters compared to both POSIX-compatible shells and cmd.exe, notably including @ { } , ;, which therefore require individual `-escaping in unquoted arguments or embedding in quoted strings - see .

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

以上信息总结如下table:

Feature POSIX shell cmd.exe PowerShell
Line-continuation / escape character Backslash (\) Caret (^) Backtick (`)
Double-quoted strings (interpolating)
Single-quoted strings (verbatim)
Reference environment variables $varName %varName% $env:varName
Reference shell-only variables $varName ❌ (no such variables exist) $varName
Command substitutions / subexpressions $(...) (...) / $(...), esp. in strings

另请参阅:

  • https://hyperpolyglot.org/shell 这些 shell 的 更全面的并置 ,但请注意 - 在撰写本文时 -有关 PowerShell 的信息不完整。

  • 链接到相应 shell 的续行文档