执行 Windows Powershell 命令将文本复制到剪贴板(包括 'r'n ')



我正在尝试执行一个powershell命令,将文本复制到windows剪贴板,包括回车和所有特殊字符。我可以使用执行命令

powershell.exe -command Set-Clipboard 'TEXT'

这不是直接在powershell控制台中,因此语法不同。

我在文本周围使用了双引号,将原始文本中的回车替换为`r`n,并将所有其他特殊字符转义为`它一直在工作,直到我找到了一个",我知道它被powershell用来表示文本字符串。

所以我改变了方法,将未转义的文本用单引号括起来(除了用1'代替2')。当然,单个引用文本中的"r"是从字面上解释的,因此不起作用。我试着把它们串在一个单独引用的文本之外,比如:

'some text here' "`r`n" 'more text here'

这在控制台中有效,但在命令中无效。尝试在任意一侧添加+,但仍然无效。

用户"TessellatingHeckler"建议-EncodedCommand,但不幸的是,我无法生成任何版本的基本64编码字符串(包括在命令中),这些字符串与通过PS控制台编码的相同字符串相匹配。所以这是行不通的。

我一直试图用一个模糊的字符串简单地替换原始文本中的回车,用单引号(文字)包裹文本,然后在PS中将其替换回`r`n。我已经直接在控制台中进行了替换,但不知道如何将其作为命令实际发送。

powershell.exe -command Set-Clipboard $Str = 'this is a test--INSERT_CRLF_HERE--1234'; $Car = '--INSERT_CRLF_HERE--'; $clr = "`r`n"; $Str = $Str -replace $Car, $clr

上面的命令可以修改吗?是否可以在不写入临时文件的情况下实现预期结果?最好能够使用单引号文本块,因为它比试图转义原始文本中的所有内容(甚至空格)更健壮、更轻量级。

Rob Simmers在另一个论坛上告诉我一个相当整洁的解决方案,我目前正在使用这个论坛。

原始文本:

Test text
!@#$%^&*()_+-=[]{}|;':",./<>?

替换了5个字符的字符串({={{}=}}'='',crlf={0}"={1}):

Test text{0}!@#$%^&*()_+-=[]{{}}|;'':{1},./<>?

Powershell.exe命令:

powershell.exe -command "$str = 'Test text{0}!@#$%^&*()_+-=[]{{}}|;'':{1},./<>?' -f [System.Environment]::NewLine, [Char] 0x22 ; Set-Clipboard $str"

输出(放置在剪贴板上的文本)-与输入相同,根据需要:

Test text
!@#$%^&*()_+-=[]{}|;':",./<>?

顺便说一句:任何调用场景中工作的完全健壮的解决方案确实需要使用-EncodedCommand和一个字符串,该字符串是命令字符串的UTF16-LE字节表示的Base64编码,但您已经说过,创建这样的字符串不是您的选择
如果要从PowerShell调用,则可以更简单地使用脚本块(请参见底部)。

更新:OP自己的答案现在包含了一个基于谨慎的字符串替换的健壮的(如果不平凡的话)解决方案
对于更简单的场景以及引用需求和陷阱的背景信息,下面的答案可能仍然很有趣。


使用您问题中的场景,这个更简单的解决方案应该可以做到(从cmd.exe验证-我们仍然不知道您从哪里调用PowerShell,但如果不涉及shell,我希望它能工作):

powershell.exe -command "Set-Clipboard "this is`r`na test""

至于其他特殊字符:

  • '可以按原样嵌入-不需要转义
  • "需要作为`"进行转义
  • $`$相同,但前提是您希望将其视为文字(与应用于常规双引号PowerShell字符串的转义相同)

如果您的用例需要传递任意预先存在的字符串,则必须使用字符串替换来执行上述转义,包括用文本`r`n替换嵌入的换行符。

如果不涉及shell(例如使用Python中的subprocess.check_output()),则上述规则应该足够,并构成一个稳健的解决方案(假设您只使用可打印字符,并且不存在字符编码问题)。

然而,从cmd.exe来看,一个不使用-EncodedCommand的完全健壮的解决方案需要额外的、非平凡的工作,因为它缺乏对嵌入双引号的正确解析:

以下cmd.exe元字符通常需要^-转义,但有时不能对进行转义:
& | < >

在以下示例中,&需要^-转义:

powershell.exe -command "Set-Clipboard "this is`r`na ^& test""

但是,如果您的字符串也嵌入(和转义)了"字符。,这些字符是否需要^-转义取决于它们相对于嵌入的"的位置;请注意,在以下示例中,&需要而不是^-转义的,实际上也不能是,因为^随后将成为字符串的一部分:

powershell.exe -command "Set-Clipboard "this is`r`na 3`" & test""

用算法预测这些变化是一项不平凡的任务。

此外,如果您的字符串具有类似cmd.exe风格的环境变量(例如%FOO%)的%...%标记,但您希望将它们视为文字,则无法转义%

有一个解决方法可能有效,但它同样取决于嵌入的"字符的存在和位置。

在下面的例子中干扰器";该技巧可用于防止%OS%:的扩展

powershell.exe -command "Set-Clipboard "do not expand: %^OS%""

然而,如果嵌入的"在它之前,则解决方法将无效(保留^),并且我所知道的在这种情况下没有直接的解决方案:

powershell.exe -command "Set-Clipboard "do not expand: 3`" %^OS%""

您必须将字符串拆分为多个部分,才能将%OS%令牌分开,并通过PowerShell表达式连接这些部分:

powershell.exe -command "Set-Clipboard ("do not expand: 3`" %" + "OS%")"

从算法上讲,您可以使用占位符字符。然后将其替换为PowerShell命令的一部分,这是您在自己的答案中使用的技术。


作为旁白:

如果要从PowerShell执行,则需要额外的转义:

powershell.exe -command "Set-Clipboard `"this is`r`na test`""

然而,从PowerShell构建一个Base64编码的字符串并传递给它并不困难-EncodedCommand,但有一个更简单的方法:使用脚本块传递命令;在这种情况下不适用任何额外的报价要求,因为-EncodedCommand随后会在幕后自动使用(与-OutputFormat Xml一起使用)
请注意,此可在PowerShell中运行。

powershell.exe -command { Set-Clipboard "this is`r`na test" }

最新更新