我正在尝试执行一个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" }