PowerShell包装器,用于将管道输入定向到Python脚本

PowerShell包装器,用于将管道输入定向到Python脚本,python,powershell,stdin,Python,Powershell,Stdin,我正试图编写一个小工具,让我管道命令输出到剪贴板。我已经通读了StackOverflow,但它们对我不起作用,因为它们不包括管道,或者因为它们没有使用函数,或者它们只是抛出了错误(或者可能是我搞砸了)。我放弃了PowerShell,决定使用Python 我创建了一个名为copytolipboard.py的Python脚本: import sys from Tkinter import Tk if sys.stdin.isatty() and len(sys.argv) == 1: #We'

我正试图编写一个小工具,让我管道命令输出到剪贴板。我已经通读了StackOverflow,但它们对我不起作用,因为它们不包括管道,或者因为它们没有使用函数,或者它们只是抛出了错误(或者可能是我搞砸了)。我放弃了PowerShell,决定使用Python

我创建了一个名为
copytolipboard.py
的Python脚本:

import sys
from Tkinter import Tk

if sys.stdin.isatty() and len(sys.argv) == 1:
  #We're checking for input on stdin and first argument
  sys.exit()

tk = Tk()
tk.withdraw()
tk.clipboard_clear()

if not sys.stdin.isatty():
    #We have data in stdin
    while 1:
        try:
            line = sys.stdin.readline()
        except KeyboardInterrupt:
            break

        if not line:
            break

        tk.clipboard_append(line)
elif len(sys.argv) > 1:
    for line in sys.argv[1]:
      tk.clipboard_append(line)


tk.destroy()
(我还没有完全测试
argv[1]
部分,所以这可能不可靠。我主要感兴趣的是阅读
stdin
,所以重要的部分是
sys.stdin

这太棒了!当我在包含脚本的目录中时,我可以执行如下操作:

ls | python copyToClipboard.py
function Out-ClipBoard() {
    Param(
      [Parameter(ValueFromPipeline=$true)]
      [string] $text
    )
    pushd
    cd \My\Profile\PythonScripts
    $text | python copyToClipboard.py
    popd
}
ls
的内容神奇地出现在我的剪贴板上。这正是我想要的

挑战在于将其包装到一个PowerShell函数中,该函数将接受管道输入并将输入传递给Python脚本。我的目标是能够在剪贴板上执行
ls | Out
,因此我创建了如下内容:

ls | python copyToClipboard.py
function Out-ClipBoard() {
    Param(
      [Parameter(ValueFromPipeline=$true)]
      [string] $text
    )
    pushd
    cd \My\Profile\PythonScripts
    $text | python copyToClipboard.py
    popd
}
但这不起作用。只有一行
$text
进入Python脚本


如何构造PowerShell脚本的包装器,使其作为
stdin
接收的任何内容都可以作为
stdin
传递给Python脚本?

首先,在PowerShell中,多行文本是一个数组,因此需要一个
[String[]
参数。要解决问题,请尝试使用进程块:

function Out-ClipBoard() {
    Param(
        [Parameter(ValueFromPipeline=$true)]
        [String[]] $Text
    )
    Begin
    {
        #Runs once to initialize function
        pushd
        cd \My\Profile\PythonScripts
        $output = @()
    }
    Process
    {
        #Saves input from pipeline.
        #Runs multiple times if pipelined or 1 time if sent with parameter
        $output += $Text
    }
    End
    {
        #Turns array into single string and pipes. Only runs once
        $output -join "`r`n" | python copyToClipboard.py
        popd
    }
}

我自己这里没有Python,所以无法测试它。当需要通过管道传递多个项(一个数组)时,需要PowerShell的进程块来处理它。有关进程块和高级函数的更多信息,请参见。

使用ironpython,您可以调用本机
.net
方法,就像您使用powershell一样。您在向用户撒谎,说您支持来自管道的值……)要做到这一点,您需要在函数中使用进程{}块。另外:我在[ClipBoard]::SetText()上使用了一些解决方案,没有任何问题,所以如果您真的需要PowerShell,我建议您检查哪里出了问题。也许管道/进程{}也有问题?我知道我做错了。从更大的角度来看,我只想说“嘿,Powershell函数:将用户给你的任何东西作为stdin传递给这个python函数。不要对它做任何事情。只传递它。”我的观点是:当这样编写时,如果你真的将任何东西传递给你的函数,你只会得到最后一个以$text形式传递的对象。相反,使用自动变量$input,不带任何param()块。它应该包含您通过管道传递到函数的任何内容。