И оно свершилось! Хотя официально Scripting Games начинаются только 15-го июня, но уже со вчерашнего дня стали известны уже 2 задания. Для начала немного информации, что и как:
В принципе, вы можете решать задания как угодно, т.к. засчитываются все, которые отвечают условиям задания.
Итак, Event1 и оба дивизиона:
Beginner Division
Из Competitors Pack нам потребуется файл 100 Meter Event.txt
Задача:
- Выяснить, как читать файл?
- Как прочитать из каждой строки поля Name, Country, Time?
- Как отсортировать содержимое файла по полю Name?
- Выбрать 3-х победителей из списка. Победителем считается тот, у кого самое маленькое время в колонке Time
- Показать поля Name, Country и Time для первых 3-х победителей.
Решение:
Побегав курсором по файлу я обнаружил тот факт, что разделителем между столбцом Name и Country является табулятор ([Tab]), а между Country и Time стоит один пробел во второй строке, а в остальных строках стоит [Tab]. Следовательно, варианты использования командлетов с параметром –Delimeter не прокатят и нужно будет разбирать всё регулярными выражениями. Первый вопрос наталкивает на необходимость чтения файла не через Get-Content, а через [system.io.file]::ReadAllText(). Но я не вижу особого криминала в использовании родного для PowerShell командлета Get-Content. Это будет несложно. Основная проблема в том, как составить регулярное выражение. Я решил разобрать имя на First Name и LastName (т.к. правильней, всё же, будет, когда сначала идёт имя, а потом фамилия), далее выбрать Country от табуляции до первого числа. Причём, тут потребуется каждую часть сделать именованной (named capture). Если открыть PowerShell In Action на 111 странице, то там можно найти описание, как делать named captures. У меня регулярное выражение получилось вот такое:
^(?<ln>\w+)..(?<fn>.*)\t(?<country>.+)(?<time>\d\.\d+)
Что делает это выражение:
- в секцию LN (LastName) попадают все буквы до первого небуквенного знака.
- далее пропускаем 2 символа (запятую и пробел).
- в секцию FN (FirstName) попадает всё до первой табуляции.
- после табуляции идёт Country и в него запишем всё, вплоть до первого числового знака.
- И числа записываем в секцию Time.
Давайте проверим его:
[↓] [vPodans] $file = gc '.\100 Meter Event.txt'
[↓] [vPodans] $file[1] -match "^(?<ln>\w+)..(?<fn>.*)\t(?<country>.+)(?<time>\d\.\d+)"
True
[↓] [vPodans] $matches
Name Value
---- -----
country Australia
ln Aaberg
fn Jesper
time 8.57
0 Aaberg, Jesper Australia 8.57
[↓] [vPodans] $file[11] -match "^(?<ln>\w+)..(?<fn>.*)\t(?<country>.+)(?<time>\d\.\d+)"
True
[↓] [vPodans] $matches
Name Value
---- -----
country Japan
ln Hansen
fn Anne Grethe
time 8.85
0 Hansen, Anne Grethe Japan 8.85
[↓] [vPodans]
и теперь соберём объект с нужными свойствами и отправим его на выход. На выходе отсортируем объекты по параметру Time и выберем первые 3 объекта:
gc "100 Meter Event.txt" | ?{$_ -match "^(?<ln>\w+)..(?<fn>.*)\t(?<country>.+)(?<time>\d\.\d+)"} |%{
$obj = "" | Select @{n='Name';e={$matches.fn + " " + $matches.ln}},
@{n='Country';e={$matches.country}},@{n='Time';e={$matches.time}}
$obj
} | sort time | select -First 3 | ft -AutoSize
и вот вывод:
[↓] [vPodans] gc "100 Meter Event.txt" | ?{$_ -match "^(?\w+)..(?.*)\t(?.+)(?
решил ещё отформатировать в Format-Table с ключом –AutoSize для красоты. Признаюсь, что это задание меня сильно озадачило. Для меня оно оказалось очень непростым (такие дела).
Advanced Division
Для этой задачи нам потребуется файл Personal Information Cards_ADV1.txt из Competitors Pack.
Задача:
- найти самую короткую строку в файле, которая содержит какой-либо текст.
- вывести на экран 3 самые короткие строчки
Решение:
В файле много пустых строк, но это не проблема. Итак, one-liner решение:
gc "Personal Information Cards_ADV1.txt" | ?{$_.trim().length -ne 0} | sort length | select -First 3
[↓] [vPodans] gc "Personal Information Cards_ADV1.txt" | ?{$_.trim().length -ne 0} | select –First 3
PPID
Claims
Street
[↓] [vPodans]
Странно, что в Advanced Division получилось такое простое задание.