Эквивалент PowerShell для "head -n-3"?

Я был в состоянии отследить основные функциональные возможности головы / хвоста:

head -10 myfile <==> cat myfile | select -first 10
tail -10 myfile <==> cat myfile | select -last 10

Но если я хочу перечислить все строки, кроме последних трех или всех строк, кроме первых трех, как вы это сделаете? В Unix я мог сделать "head -n-3" или "tail -n+4". Не совсем понятно, как это сделать для Powershell.

6 ответов

Решение

Как и параметры -First и -Last, также есть параметр -Skip, который поможет. Стоит отметить, что -Skip основан на 1, а не на нуле.

# this will skip the first three lines of the text file
cat myfile | select -skip 3

Я не уверен, что в PowerShell есть что-то, что возвращает вам все, кроме последних n предварительно собранных строк. Если вы знаете длину, вы можете просто вычесть n из числа строк и использовать параметр -First из select. Вы также можете использовать буфер, который пропускает строки только после заполнения.

function Skip-Last {
  param (
    [Parameter(Mandatory=$true,ValueFromPipeline=$true)][PsObject]$InputObject,
    [Parameter(Mandatory=$true)][int]$Count
  )

  begin {
    $buf = New-Object 'System.Collections.Generic.Queue[string]'
  }

  process {
    if ($buf.Count -eq $Count) { $buf.Dequeue() }
    $buf.Enqueue($InputObject)
  }
}

Как демо:

# this would display the entire file except the last five lines
cat myfile | Skip-Last -count 5

Полезная информация распределена по другим ответам здесь, но я думаю, что полезно иметь краткое резюме:

Все строки кроме первых трех

1..10 | Select-Object -skip 3
returns (one per line): 4 5 6 7 8 9 10

Все строки, кроме трех последних

1..10 | Select-Object -skip 3 -last 10
returns (one per line): 1 2 3 4 5 6 7

То есть вы можете сделать это с помощью встроенных команд PowerShell, но есть одно неудобство, связанное с указанием входящего размера. Простой обходной путь - просто использовать константу, большую, чем любой возможный ввод, и вам не нужно будет знать размер априори:

1..10 | Select-Object -skip 3 -last 10000000
returns (one per line): 1 2 3 4 5 6 7

Более чистый синтаксис заключается в использовании, как предложил Кит Хилл, командлета Skip-Object из расширений сообщества PowerShell (функция Skip-Last в ответе Goyuix работает аналогично, но использование PSCX избавляет вас от необходимости поддерживать код):

1..10 | Skip-Object -last 3
returns (one per line): 1 2 3 4 5 6 7

Первые три строки

1..10 | Select-Object –first 3
returns (one per line): 1 2 3

Последние три строки

1..10 | Select-Object –last 3
returns (one per line): 8 9 10

Средние четыре строки

(Это работает, потому что -skip обрабатывается до -firstнезависимо от порядка параметров в вызове.)

1..10 | Select-Object -skip 3 -first 4
returns (one per line): 4 5 6 7

Все кроме последнего n может быть сделано с

... | select -skiplast $n

Если вы используете расширения сообщества PowerShell, существует командлет Take-Object, который будет проходить через все выходные данные, кроме последних N элементов, например:

30# 1..10 | Skip-Object -Last 4
1
2
3
4
5
6

Вы можете сделать это так:

[array]$Service = Get-Service
$Service[0] #First Item
$Service[0..2] #First 3 Items
$Service[3..($Service.Count)] #Skip the first 3 lines
$Service[-1] #Last Item
$Service[-3..-1] #Last 3 Items
$Service[0..($Service.Count -4)] #Skip the last 3 lines

Все кроме первого n может быть сделано с

... | Select -skip $n

Однако все "но последнее m"ничего не встроено. Можно выполнить загрузку всего ввода в массив, чтобы получить длину - конечно, для большого ввода, который может привести к необоснованным требованиям к памяти.

Другие вопросы по тегам