1

У меня есть подпроцесс, который я хочу вызвать из powershell, который может быть интерактивным или я могу направить данные прямо в него. Например:

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

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

Я хочу создать функцию, которую можно использовать для переноса вызова в такой процесс. Я могу сделать это:

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())"

Или я могу сделать это:

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())"

Я не могу понять, как написать функцию, которая обрабатывает оба случая. Если он вызывается без конвейера, я хочу, чтобы он запускал подпроцесс, который читает из stdin, и если он вызывается с входом конвейера, я хочу, чтобы он передавал это в stdin подпроцесса. Я могу это сделать?

2 ответа2

2

Вы можете проверить значение $MyInvocation.ExpectingInput чтобы узнать, ожидала ли ваша функция какой-либо конвейерный ввод или это первый элемент конвейера.

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

Определите параметр в функции, которая будет хранить ваши данные. Затем проверьте, указан ли параметр, и действуйте соответствующим образом. Возможно, вам придется внести некоторые изменения в связи с тем, как PowerShell передает данные во внешние программы, но основная идея остается в силе.

Пример Barebone:

Использование:

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

Здесь я передаю массив в функцию Invoke-Python .

Результат:

  • 'foo' будет передан питону
  • Затем функция встретит пустой параметр и вызовет интерактивный питон
  • После того, как вы выйдете из интерактивного питона, функция направит 'бар' к питону

Функция Invoke-Python :

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
        }
    }
}

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .