如何使 ($Line_1`n$Line_2) 在 CMD 脚本中工作?

如何解决如何使 ($Line_1`n$Line_2) 在 CMD 脚本中工作?

我在 CMD 脚本文件中使用以下代码

PowerShell Add-Type -AssemblyName System.Windows.Forms;^
$Line_1 = 'Hello!';^
$Line_2 = 'How are you?';^
[System.Windows.Forms.MessageBox]::Show($Line_1)

以上只会显示($Line_1)
如果使用 ($Line_1`n$Line_2),则不会显示任何内容。

如何让它同时显示$Line_1$Line_2

解决方法

最简单的解决方案是(注意 \"$Line_1`n$Line_2\" 部分):

PowerShell -c Add-Type -AssemblyName System.Windows.Forms; ^
$Line_1 = 'Hello!'; ^
$Line_2 = 'How are you?'; ^
[System.Windows.Forms.MessageBox]::Show(\"$Line_1`n$Line_2\")

请注意,我已明确添加了 -c (-Command) 参数名称以表示正在传递 PowerShell 命令字符串。虽然这在 Windows PowerShell 中不是必需的,默认为 -Command,但在 PowerShell (Core) 7+ 中,-File 是现在是默认设置 - 请参阅 Windows PowerShellPowerShell (Core) 7+CLI 文档

也就是说,您必须$Line_1`n$Line_2 中使用 "...",一个 expandable string,并且您必须\-转义 { {1}} 个字符,以便 PowerShell 不会将它们作为其命令行解析的一部分剥离(在没有整体双引号的情况下," 也可以使用) .


不幸的是,解析规则在使用 for /f改变,以便逐行处理 PowerShell 的输出和/或将其捕获到变量中:

注意:下面使用 """ 来生成控制台输出,只是为了使用与 [Console]::WriteLine() 方法调用类似的语法,同时允许 {{1} 捕获某些内容}}。在现实生活中,没有很好的理由调用 [System.Windows.Forms.MessageBox]::Show()

for /f
  • [Console]::WriteLine() 必须另外被转义(在 for /f "delims=" %%l in (' PowerShell -c Add-Type -AssemblyName System.Windows.Forms^; ^ $Line_1 ^= 'Hello!'^; ^ $Line_2 ^= 'How are you?'^; ^ [Console]::WriteLine^(\"$Line_1`n$Line_2\"^) ') do echo [%%l] 所看到的 =,; ( ) 字符串之外)。

  • 如果您另外在 cmd.exe 中包含一个 "..." 字符串以防止空格规范化(请参阅下一节)该字符串则需要 \"...\"-转义嵌入的 "..." 元字符,您必须莫名其妙地在 initial ^ 前面加上 cmd.exe;例如,
    "

  • 换行符(位于命令内部行末尾的 ^)实际上在 ^"\"Marley ^& Me\"" 中是可选的,但为了一致性而将它们包含在内。 >


引用和转义要求摘要

  • 带有续行的多行技术(行尾的 ^) - 在语法上不能使用 for /f 引用整个 命令,因为 ^ 不支持双引号多行 strings - 需要小心的 "..."-转义所有 cmd.exe 元字符,应该传递给PowerShell,特别是^,此外,如果从cmd.exe 语句中调用PowerShell& | < > ^ - 除非这些字符碰巧是 for /f 视为 double 引用的子字符串的一部分;例如,放置在 ,; = ( ) 字符串内的 cmd.exe - 例如& - 必须不能\"...\"-escaped(但见下文关于空白规范化)。

    • 作为一个例外,元字符 \"$Line_1`n & $Line_2\" 必须始终转义为 ^(仅适用于批处理文件,不适用于命令提示符 - 请参阅{{ 3}}).

    • 此外,如果 % 有效(或 %%setlocal enabledelayedexpansion 开头),cmd.exe 也必须转义,但如下所示:

      • 作为 /V:ON (sic) outside ! 所看到的 ^^! 字符串(其中另一个元字符只需要 一个 cmd.exe)
      • 作为 "..." inside 这样的字符串(其他元字符需要没有转义)。
    • 当通过 ^ 调用时,续行是可选 - 也就是说,您可以省略命令内部行末尾的 ^!

  • 每个语句都必须以 for /f 结尾(正如您所做的那样),因为换行符 (^) 导致输入之间没有 换行符行,因此 PowerShell 将它们视为一行,多个语句必须以 ; 分隔。

  • 因为 ^ 和 PowerShell 的 initial 命令行解析都不知道单引号字符串 (;) 并且因为 转义 cmd.exe 字符串中的 '...' 字符在命令行解析过程中没有 语法 功能,如果这些字符串包含空格,则会被分解为 多个 参数:

    • 实际上,这些字符串中多个相邻空格的运行被标准化为每个单个空格。例如,"\"...\" 最终被 PowerShell 视为 'How are you?'\"How are you?\"

    • 为避免这种情况,另外将这些字符串括在未转义 'How are you?'中(如果 em>整个命令包含在 "How are you?") 中:
      ""..."

    • PowerShell 最终应将其视为 "'How are you?'"(插值)字符串,但棘手的部分是 "\"How are you?\"" 无法识别 "..."-转义 cmd.exe 字符,因此 it\ 视为双引号字符串 ("),后跟一个不带引号的字符串 ("\"How are you?\""),后跟另一个双引号字符串 ("\")。因此,此类字符串中的任何 How are you?\ 元字符都必须再次进行 "" 转义才能传递到 PowerShell(这适用于包装的 cmd.exe字符串,例如 ^);例如:'...'

      • PowerShell (Core) 7+ only 中,您可以通过使用 "'How are you?'" 而不是 "\"rock ^& roll"\" 来避免这种额外的 ^-escaping转义的 PowerShell ""(在 Windows PowerShell 上会再次导致空白规范化),与封闭的未转义 \" 结合有效地导致 三重双引号:"

PowerShell 如何解析传递给其 CLI 的 "..." / """How are you?""" 参数的参数:

PowerShell 为您提供传递命令字符串之间的选择

  • either:作为单个参数,包含在整体-Command中;例如:

    • -c
  • 或:多个 参数 - 可能单独使用 "..." 引用 - 然后 PowerShell 将这些参数连接起来形成一个字符串;例如:

    • powershell -c "Get-Date -Format 'yyyy MMM'"

在这两种情况下,未转义 "..." 个字符都从参数中剥离,因为为了命令行 而不是生成的 PowerShell 命令。

剥离语法 powershell -c Get-Date -Format "'yyyy MMM'" 字符并用空格连接结果参数后(如果适用),Powershell 将结果字符串解释为 PowerShell 代码

注意:这与您使用 " CLI 参数调用 脚本文件 并将参数传递给它时解析参数的方式有根本的不同 - 有关更多信息,请参阅 this answer .

,

显然 $Line_1 + "`n" + $Line_2"$Line_1`n$Line_2" 工作正常。将命令字符串从 cmd 发送到 PowerShell 非常棘手,因为它具有传统的怪癖:

  • 在 cmd () 中,不同地方的特殊字符表示一个块
  • 令牌分隔符不仅是 <space><tab>,还有 ; , = <0x0B> <0x0C> and <0xFF>。这会更改 cmd 的标记化行为,但被调用的命令可能会再次使用其规则重新解析命令

根据文档,PowerShell 期望最后一个参数中的单个字符串中的命令(这并不完全正确,因为文档没有正确更新),所以你需要引用整个内容或转义所有的分隔符。最简单的解决方案是使用单行并像这样转义 "`n" 中的引号

PowerShell "Add-Type -AssemblyName System.Windows.Forms; $Line_1 = 'Hello!'; $Line_2 = 'How are you?'; [System.Windows.Forms.MessageBox]::Show($Line_1 + \"`n\" + $Line_2)"

如果您想将命令放在多行中,则不能引用字符串。要将整个内容作为单个参数,现在您需要转义所有空格(在这种情况下您不需要转义 ;,可能是因为在将命令行传递给 PowerShell 后,它会调用 {{ 1}} 并再次解析整个事情本身)

GetCommandLineW

或者,您可以通过直接使用 PowerShell Add-Type^ -AssemblyName^ System.Windows.Forms;^ $Line_1^ =^ 'Hello!';^ $Line_2^ =^ 'How^ are^ you?';^ [Windows.Forms.MessageBox]::Show($Line_1^ +^ \"`n\"^ +^ $Line_2)" 获取新行来避免使用 "`n" 字符串

[char]10

最后一个无需任何转义即可工作的解决方案,它利用 PowerShell 的 PowerShell -Command Add-Type -AssemblyName System.Windows.Forms;^ $Line_1 = 'Hello!';^ $Line_2 = 'How are you?';^ [System.Windows.Forms.MessageBox]::Show($Line_1 + [char]10 + $Line_2) 选项接收 UTF-16 命令字符串的 base64 编码字符串。您可以通过在 PowerShell 中运行它来获取编码版本

EncodedCommand

获得编码版本后,您可以从 cmd 调用它

$str = @'
>> Add-Type -AssemblyName System.Windows.Forms;
>> $Line_1 = 'Hello!';
>> $Line_2 = 'How are you?';
>> [System.Windows.Forms.MessageBox]::Show($Line_1 + "`n" + $Line_2)
>> '@
PS C:\Users\phucl> [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($str))
QQBkAGQALQBUAHkAcABlACAALQBBAHMAcwBlAG0AYgBsAHkATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVwBpAG4AZABvAHcAcwAuAEYAbwByAG0AcwA7AAoAIAA9ACAAJwBIAGUAbABsAG8AIQAnADsACgAgAD0AIAAnAEgAbwB3ACAAYQByAGUAIAB5AG8AdQA/ACcAOwAKAFsAUwB5AHMAdABlAG0ALgBXAGkAbgBkAG8AdwBzAC4ARgBvAHIAbQBzAC4ATQBlAHMAcwBhAGcAZQBCAG8AeABdADoAOgBTAGgAbwB3ACgAIAArACAAIgAKACIAIAArACAAKQA=
,

有多种连接字符串的方法可以查找,但最简单的方法可能是使用 + 符号。 `n 是一个换行符,它将第 2 行置于第 1 行下方。请注意,` 是一个反引号(通常与波浪号 ~ 位于同一键上)

[System.Windows.Forms.MessageBox]::Show($Line_1 + "`n" + $Line_2)

再次查看您的帖子后,我注意到您与 ($Line_1`n$Line_2) 很接近。你只是缺少一些双引号

[System.Windows.Forms.MessageBox]::Show("$Line_1`n$Line_2")

Powershell 很乐意将变量放在双引号内时替换它们的值。您可以阅读有关可扩展字符串 herehere

的更多信息

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-