Как получить номера строк с помощью PowerShell?

Вопрос или проблема

У меня есть простой текстовый файл:

$ cat food.txt
Яблоки
Бананы
Морковка

Linux/Cygwin

Я могу придумать несколько способов получить номера строк в Linux/Cygwin:

$ nl food.txt
     1  Яблоки
     2  Бананы
     3  Морковка

$ cat -n food.txt
     1  Яблоки
     2  Бананы
     3  Морковка

$ less -NFX food.txt
      1 Яблоки
      2 Бананы
      3 Морковка

PowerShell

Лучший способ, который я придумал, это:

Обновление 2017-11-27: (1) Небольшая корректировка: Out-String -Stream, чтобы принудительно преобразовать эти надоедливые объекты в текст. (2) Примечание: Я ищу что-то, что будет принимать ВХОДНЫЕ ДАННЫЕ PIPELINE.

PS C:\> function nl{$input | Out-String -Stream | Select-String '.*' | Select-Object LineNumber, Line}

PS C:\> cat .\food.txt | nl
LineNumber Line
---------- ----
         1 Яблоки
         2 Бананы
         3 Морковка

Есть ли более простой способ? Короче? Что-то встроенное в PowerShell?

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

Function nl 
{
<# .Synopsis
    Имитировать инструмент Unic / Linux nl для нумерации строк
   .Description
    Печать содержимого файла с номерами строк без поддержки оригинальных опций nl
   .Example
     nl .\food.txt
#>
  param (
    [parameter(mandatory=$true, Position=0)][String]$FileName
  )

  process {
    If (Test-Path $FileName){
      Get-Content $FileName | ForEach{ "{0,5} {1}" -f $_.ReadCount,$_ }
    }
  }
}

Пример вывода:

> nl .\food.txt
    1 Яблоки
    2 Бананы
    3 Морковка

Это сработает и будет работать с любой командой, которая производит вывод:

$i = 1; cat food.txt | % {$i++;"$($i-1) `t $_"}

Вот вывод:

1        Яблоки
2        Бананы
3        Морковка

Вот пример с выводом каталога:

$i = 1; dir | % {$i++;"$($i-1) `t $_"}

Вот вывод:

1        фоны
2        загрузка
3        inetpub
4        PerfLogs
5        Program Files
6        Program Files (x86)
7        Riot Games
8        Пользователи
9        Windows
10       Reflect_Install.log

Очевидно, если вы хотите, чтобы нумерация строк начиналась с 0, то установите $i = 0.

Самый короткий метод:

cat log.txt|oss|sls .|select linenumber,line

Предположим, у нас есть food.txt или создадим его с:

Set-Content food.txt "Яблоки`r`nБананы`r`nМорковка"

Детализированный метод будет следующим:

Get-Content food.txt | Select-String . | Select-Object LineNumber,Line

# LineNumber Line
# ---------- ----
#          1 Яблоки
#          2 Бананы
#          3 Морковка

Сокращённая версия

Вы можете сократить команду, используя их псевдонимы gc (Get-Content), sls (Select-String) и select (Select-Object), что даёт:

gc food.txt | sls . | select linenumber,line

Что происходит?

  • Get-Content: извлечет содержимое файла
  • Select-String .: Select-String является фильтром для ввода строки. В регулярном выражении . является подстановочным знаком для всего, так что это на самом деле не фильтрует ничего, но мы используем Select-String как умный прием, потому что он разбивает строку на объект MatchInfo, который содержит множество полей, таких как:
    1. LineNumber: то, что мы хотим добавить.
    2. Line: содержимое строки.
  • Select-Object: мы используем его для фактического выбора полей LineNumber и Line.

Если вы уберете Select-Object, то на самом деле покажется, что ничего не произошло, потому что метод ToString() от MatchInfo только печатает часть Line, так что, явно указав поля с помощью Select-Object, он преобразуется в PSCustomObject, чей метод ToString() будет отображать все поля в удобном читаемом табличном формате.

Использование традиционного for-each

Если вы не хотите использовать хитрые приемы, вы можете придерживаться традиционного метода for-each, который в powershell можно сократить до %

$i = 1; gc food.txt | % {"$i `t $_"; $i++}

Это сделает:

  1. Инициализирует $i = 1
  2. Получит содержимое food.txt
  3. for-each строку food.txt:
    1. Вернуть "$i `t $_":
      1. $i: номер строки
      2. `t: TAB (табуляция)
      3. $_: содержимое из конвейерной gc food.txt
    2. $i++: увеличить $i

.

Ответ или решение

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

Основные методы получения номеров строк

1. Использование встроенных команд

Самым простым и удобным способом является использование комбинации команд Get-Content, Select-String и Select-Object. Вот как это можно сделать:

gc food.txt | sls . | select linenumber, line

Объяснение команд:

  • gc — это сокращение для Get-Content, которое считывает содержимое файла.
  • sls . — это Select-String, который ищет все строки (так как . является шаблоном для любой строки), преобразуя каждую строку в объект MatchInfo, содержащий необходимые поля, такие как LineNumber и Line.
  • select linenumber, line — используется для выбора конкретных полей из объекта.

Такой подход печатает содержимое файла с номерами строк, как показано ниже:

# LineNumber Line
# ---------- ----
#          1 Apples
#          2 Bananas
#          3 Carrots

2. Использование цикла

Если вам больше нравятся традиционные методы итерации, вы можете использовать цикл ForEach в комбинации с инкрементируемой переменной для номерования строк.

$i = 1; gc food.txt | % {"$i `t $_"; $i++}

Что происходит в этой команде:

  • $i = 1 — инициализация переменной для номера строки.
  • gc food.txt — считывание содержимого файла.
  • % — это сокращение для ForEach-Object, который перебирает каждую строку в файле.
  • "$it $_"` — формирует строку с номером и содержимым.
  • $i++ — инкрементирует номер строки после обработки каждой строки.

Вывод будет выглядеть так:

1        Apples
2        Bananas
3        Carrots

3. Кастомные функции

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

Function nl {
    param (
        [parameter(mandatory=$true, Position=0)][String]$FileName
    )
    process {
        If (Test-Path $FileName) {
            Get-Content $FileName | ForEach-Object { "{0,5} {1}" -f ($_.ReadCount), $_ }
        }
    }
}

Эта функция принимает имя файла в качестве параметра и выводит содержимое с номерами строк. Примените функцию на примере вашего файла:

nl .\food.txt

Заключение

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

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

Оцените материал
Добавить комментарий

Капча загружается...