Powershell: как вы читаете и пишете ввод / вывод в одном конвейере? - PullRequest
4 голосов
/ 24 июня 2009

Я хотел бы иметь возможность набирать быстрые, простые команды, которые манипулируют файлами на месте. Например:

# prettify an XML file
format-xml foo | out-file foo

Это не сработает, потому что конвейер спроектирован как "жадный". Нижележащий командлет получает блокировку записи в файл, как только вышестоящий командлет обрабатывает первую строку ввода, что останавливает вышестоящий командлет от чтения остальной части файла.

Существует много возможных обходных путей: запись во временные файлы, разделение операций на несколько конвейеров (сохранение промежуточных результатов в переменных) или аналогичные. Но я полагаю, что это действительно распространенная задача, для которой кто-то разработал быстрый, дружественный к оболочке ярлык.

Я пробовал это:

function Buffer-Object 
{
    [CmdletBinding()]
    param (
        [parameter(Mandatory=$True, ValueFromPipeline=$True)]
        [psobject] $InputObject
    )

    begin { $buf = new-list psobject }
    process { $buf.Add($InputObject) }
    end { $buf }
}
format-xml foo | buffer-object | out-file foo

В некоторых ситуациях работает нормально. Сопоставленный с коротким псевдонимом и объединенный в общий дистрибутив, такой как PSCX, он будет «достаточно хорош» для быстрых интерактивных задач. К сожалению, похоже, что некоторые командлеты (включая внешний файл) захватывают блокировку в своем методе Begin {}, а не в Process {}, поэтому это не решает этот конкретный пример.

Другие идеи?

1 Ответ

7 голосов
/ 24 июня 2009

Насколько я помню (сейчас не могу проверить), вы можете прочитать весь файл в память с помощью обозначения пространства имен:

${c:file1.txt} = ${c:file1.txt} -replace "a" "o"
...