Detectar entrada da função powershell é redirecionada

1

Eu tenho um subprocesso que eu quero chamar do PowerShell que pode ser interativo ou eu posso enviar dados diretamente para ele. Por exemplo:

# This is interactive:
& c:\python27\python.exe

# This takes redirected input:
echo hi | & c:\python27\python.exe -c "print repr(raw_input())"

Eu quero criar uma função que possa ser usada para encapsular uma chamada para esse processo. Eu posso fazer isso:

function python() {
    & c:\python27\python.exe @args
}

# This starts an interactive prompt:
python

# The piped data disappears and the process still reads from the console:
echo hi | python -c "print repr(raw_input())"

Ou eu posso fazer isso:

function python() {
    $input | & c:\python27\python.exe @args
}

# This doesn't accept interactive input:
python

# The piped data is passed through to the sub-process as intended:
echo hi | python -c "print repr(raw_input())"

Não consigo descobrir como escrever uma função que lide com os dois casos. Se for invocado sem um pipeline, quero que ele inicie um subprocesso que leia stdin e, se ele for invocado com uma entrada de pipeline, quero que ele seja alimentado no stdin do subprocesso. Posso fazer isso?

    
por Weeble 10.04.2015 / 14:44

2 respostas

2

Você pode verificar o valor da expressão $MyInvocation.ExpectingInput para descobrir se sua função esperava alguma entrada de pipeline ou se é o primeiro elemento do pipeline.

function python {
    if($MyInvocation.ExpectingInput){
        $input | & c:\python27\python.exe @args
    }else{
        & c:\python27\python.exe @args
    }
}
    
por 12.04.2015 / 01:24
1

Defina o parâmetro na função, que armazenará seus dados. Em seguida, verifique se o parâmetro é fornecido e aja de acordo. Você pode ter que fazer alguns ajustes devido à maneira como o PowerShell passa os dados para programas externos , mas a ideia básica permanece.

Exemplo de barebone:

Uso:

'foo', '', 'bar' | Invoke-Python

Aqui estou passando um array para a função Invoke-Python .

Resultado:

  • 'foo' será canalizado para o python
  • Em seguida, a função encontrará um parâmetro vazio e invocará o python interativo
  • Depois de sair do python interativo, a função canalizará 'bar' para o python

Invoke-Python function:

function Invoke-Python
{
    [CmdletBinding()]
    Param
    (
        # This parameter will catch your input data
        [Parameter(ValueFromPipeline = $true)]
        [string]$InputObject
    )

    # This block runs when pipeline is initialized.
    # It doesn't have access to the parameters,
    # they are not yet parsed at this time.
    Begin
    {
        # Set path to the python
        $PythonPath = 'c:\python27\python.exe'
    }

    # This block runs for each pipeline item
    Process
    {
        # Check, is there anything passed in the InputObject parameter
        if($InputObject)
        {
            Write-Host 'We have some data, let''s pipe it into the python'
            $InputObject | & $PythonPath @('-c', 'print repr(raw_input())')
        }
        else
        {
            Write-Host 'No data, let''s just launch interactive python'
            & $PythonPath
        }
    }
}
    
por 10.04.2015 / 15:41

Tags