Powershell:读取主机中出现意外回显
我正在尝试在powershell中编写一个简单的文本操作过滤器(W10-64位上的5.1)。我的目标是将其作为批处理(.bat)中管道的一部分使用,例如: 我面临一个奇怪的问题:“读取主机”cmdlet总是回显其输入。例如:Powershell:读取主机中出现意外回显,powershell,batch-file,Powershell,Batch File,我正在尝试在powershell中编写一个简单的文本操作过滤器(W10-64位上的5.1)。我的目标是将其作为批处理(.bat)中管道的一部分使用,例如: 我面临一个奇怪的问题:“读取主机”cmdlet总是回显其输入。例如: echo 1234 | powershell "$a=Read-Host" 产生 1234 (注:见附件) 我怎样才能避免这种意外的回音?在powershell中是否有其他读取STDIN的方法 注2:我知道我可以在powershell中完成所有管道工
echo 1234 | powershell "$a=Read-Host"
产生
1234
(注:见附件)
我怎样才能避免这种意外的回音?在powershell中是否有其他读取STDIN的方法
注2:我知道我可以在powershell中完成所有管道工作,但由于许多原因,这不适合我的情况。我想要的是一个“通用过滤器”,适合作为“.bat”中管道的一部分。而且,不,存储中间数据的临时文件不是一个选项
编辑:如“COMO”所述,MS文档中提到的关于Read_主机:
无法将输入管道传输到此cmdlet 因此,试图让它发挥作用是没有意义的 EDIT2:正如“mklement0”所解释的,“[Read_Host]确实接受管道,即来自外部的stdin输入,例如当提供给PowerShell的CLI时”。真正的问题是,它旨在简化用户输入,而不是提供对stdin的通用访问 实际的问题是:在powershell中有没有其他读取STDIN的方法 在powershell中是否有其他读取STDIN的方法 这已经发生了,您只需要知道如何钩住它-例如:
C:\> echo "camelCase" |powershell -Command "$input |ForEach-Object ToUpper"
CAMELCASE
由于PowerShell和CMD使用的语法稍有不同,因此可能会有点难以摆脱,因此我强烈建议将您的筛选器放在脚本文件中并调用以下内容:
# myUpperCaseFilter.ps1
$input |ForEach-Object ToUpper
在powershell中是否有其他读取STDIN的方法
这已经发生了,您只需要知道如何钩住它-例如:
C:\> echo "camelCase" |powershell -Command "$input |ForEach-Object ToUpper"
CAMELCASE
由于PowerShell和CMD使用的语法稍有不同,因此可能会有点难以摆脱,因此我强烈建议将您的筛选器放在脚本文件中并调用以下内容:
# myUpperCaseFilter.ps1
$input |ForEach-Object ToUpper
此答案是对的补充,它显示了处理通过管道(stdin)传递到PowerShell的数据的正确方法
:
- 不在PowerShell会话中接受来自的管道输入,这是文档所指
- 是否接受管道,即从外部输入的stdin[1]输入,例如提供给PowerShell的CLI时
- 在交互式使用中,
只读取一行。读取主机
- 因为即使使用stdin输入也会模拟交互行为,输入也会始终回显到显示器上,这是无法抑制的
- 与所有其他cmdlet(以及表达式)不同,它需要显式使用
来处理stdin数据,如Mathias的答案所示-$input
隐式读取stdin输入Read Host
- 这意味着您必须完全通过
调用使用stdin输入,或者使用读取主机
将其转发给其他命令$input
- 这意味着您必须完全通过
这使得从PowerShell外部将字符串输送到
读取主机
的合法用例只剩下一个:
- 自动响应给定命令/脚本的交互提示;e、 g:
C:\>echo y | powershell -c "$response = Read-Host 'Continue (y/n)'; if ($response.Trim() -ne 'y') { exit 2 }; 'continuing...'" Continue (y/n): y continuing...
- 有关更多信息,请参阅
相反,这意味着您不应该使用
readhost
来收集变量中的stdin输入,因为只读取了一行,并且存在不必要的回显行为
通常,您只需通过命令将stdin输入传递给其他命令,如Mathias的回答所示要预先显式收集变量中的所有stdin输入,可以将$()
,the(或@()
,the)应用于$输入
枚举器:
C:\>(echo abc & echo def) | powershell "$allInput=$($input); \"$($allInput.Count) lines received.\""
2 lines received.
[1] 标准输入流stdin是操作系统级的概念,标准输出流stdout和stderr也是如此。相比之下,PowerShell实现了自己的流系统:概念主题中描述了6个(!)输出流;成功输出流(number
1
)和错误流(2
)分别类似于stdout和stderr。但是,没有类似的标准输入法:(流)对其他命令的输入仅通过管道提供(也不通过),这一回答补充了这一点,说明了处理通过管道(标准输入法)传递到PowerShell的数据的正确方法
:
- 不在PowerShell会话中接受来自的管道输入,这是文档所指
- 是否接受管道,即从外部输入的stdin[1]输入,例如提供给PowerShell的CLI时
但是,这也有一些限制:
- 在交互式使用中,
读取主机
只读取一行。
- 因为即使使用stdin输入也会模拟交互行为,输入也会始终回显到显示器上,这是无法抑制的
- 与所有其他cmdlet(以及表达式)不同,它需要显式使用
$input
来处理stdin数据,如Mathias的答案所示-Read Host
隐式读取stdin输入
- 这意味着您必须完全通过
读取主机
调用使用stdin输入,或者使用$input
将其转发给其他命令
这使得从PowerShell外部将字符串输送到读取主机
只剩下一个合法的用例