Пишу, по большей части, про историю, свою жизнь и немного про программирование.

Ещё о PowerShell

Всё-таки PowerShell прекрасен. Вот это вот:

cat user-agents.log | sort -u

одинаково работает и под bash и под PowerShell! Конечно, более «чистый» PowerShell выглядит как на листинге ниже:

Get-Content user-agents.log | Sort-Object -unique

Команда «Get-Content» имеет алиас «cat», «Sort-Object» — «sort», а ключ «unique» сокращается до «u».

Или вот, на bash не совсем похоже, но что проиходит догадаться просто:

ls | where {!$_.length} | %{rm $_}
15 комментариев
hshhhhh.name 2009

нравится мне этот подход: PS хорош потому что он почти как баш.

okakiy.livejournal.com 2009

А такое могет?

cat access.log |grep ’GET /tratata’ | cut -f1 -d’ ’|sort -u

Евгений Степанищев (bolknote.ru) 2009

Комментарий для hshhhhh.name:

Он лучше.

Евгений Степанищев (bolknote.ru) 2009

Комментарий для okakiy.livejournal.com:

Именно в таком синтаксисе — нет, команды будут другие, но именно это сделать конечно можно. PowerShell мощнее bash’а с его внешними командами. Можно, например, превратить лог в набор объектов и проверять не просто какие-то строки, разбитые по пробелам, а свойства этого объекта.

Вот, если взять мой пример:

ls | where {!$_.length} | %{rm $_}

здесь команда ls возвращает набор объектов, я выделяю только те, у которых поле length равно нулю и удаляю только эти файлы. При этом работает, грубо говоря, toString — когда rm пытается получить строку из объекта, он получает имя этого объекта.

Точно так же можно сделать с логами. А можно и традиционно работать — как в bash’e.

Евгений Степанищев (bolknote.ru) 2009

Комментарий для okakiy.livejournal.com:

Так как мне всё равно делать пока нечего, покажу как переписать этот пример практически одни в один, без перехода к объектам:

cat access.log | Select-String -s ’GET /tratata’ | %{([string] $_).Split()[1]} | sort -u

Евгений Степанищев (bolknote.ru) 2009

Комментарий для okakiy.livejournal.com:

Select-String — это такой аналог grep, без ключа «s» было бы совпадение по регулярке, ключ «s» («simpleMatch», кажется, не помню точно полное название) означает, что искаться будет просто вхождение. %{} — это короткий алиас для Foreach-Item, на каждом этапе цикла значение попадает в $_, поскольку после Select-String там не строка, а объект-совпадение, то я преобразую его к строке ([string] — typecast), у строки есть метод Split, который по-умолчанию бьёт по пробелу, из получившего массива беру первое значение (можно взять несколько: [1,6,2,7]), потом как в bash — сортировка и отбор уникальных.

jankkhvej (jankkhvej.blogspot.com) 2009

Наблюдаю useless use of cat, многократно.

http://en.wikipedia.org/wiki/Cat_%28Unix%29#Useless_use_of_cat

Неужели PowerShell так зафейлил идею? Или это вы им так пользуетесь?

Евгений Степанищев (bolknote.ru) 2009

Комментарий для jankkhvej.blogspot.com:

Я вас не понял. В PowerShell есть команда для чтения файла — Get-Content, для удобства у неё есть алиас — «cat», чтобы тем, кто программировал на bash было проще перейти на этот shell.

Это не bash, там всё работает по-другому. cat и sort — это на деле Get-Content и Sort-Object, это не программы и не команды, можно сказать это операторы. Вас же не смутит, если я в PHP сделаю вот так: «$a = file(’log.log’); sort($a);»? Как видно, функция sort тут не читает файл, она этого не умеет. Не умеет Sort-Object читать файлы, несмотря на то, что у неё есть алиас «sort». Sort-Object всего лишь сортирует объекты (настоящие объекты, со свойствами и методами), которые подаются на вход.

Так что никакого useless cat тут нет, потому что нет того «cat», который упоминается в Википедии.

jankkhvej (jankkhvej.blogspot.com) 2009

В PHP не смутит, потому что sort() там работает с array, это же очевидно, что нужно использовать file(). Что меня там сущает, так это то, что там file handle, полученный после fopen(), нельзя передать в sort(), и более того, в краску вгоянет то, что его нельзя передать и в file(), которая ждёт просто строки пути к файлу!
Но на то это ж и PHP, а не что-нибудь более цельное и продуманное. Тот же Perl, который делает, например, так:
open FH, ’/var/log/apache2/access.log’ or die «error: $!»;
@content = sort <FH>;
В Perl функция sort() тоже не умеет читать файл, однако читать файл и возвращать данные оттуда массивом умеет оператор < >. Аналогично поступает bash, разбирая командную строку и обрабатывая перенаправления.

Так что — вход у Sort-Object не может принять непосредственно контент из файла?
Нельзя что ли написать Sort-Object < access.log | Select-String чего-то_там ?

Евгений Степанищев (bolknote.ru) 2010

Комментарий для jankkhvej.blogspot.com:

Из чего мы делаем вывод, что языки программирования разные и странной было бы ожидать от PowerShell поведения bash.

Так что — вход у Sort-Object не может принять непосредственно контент из файла? Нельзя что ли написать Sort-Object < access.log

А чем операция „<“ существенно отличается от «cat file |»? Синтаксический сахар, не более. В версии 1.0, которую я более-менее знаю, такого сахара нет. Во второй версии, возможно, он есть. Но я не понимаю почему он принципиален.

Евгений Степанищев (bolknote.ru) 2010

Комментарий для jankkhvej.blogspot.com:

То есть в языке, где cat — внешняя программа, такой синтаксис имеет кучу плюсов, в bash он «сахаром» не является. Внешняя программа cat прочитает файл, он сохранится в специальный временный файл, пойдёт по pipe и так далее.

В PowerShell Get-Content (или алиас «cat») — это командлет (≈оператор), там язык имеет возможность более умно распорядиться ресурсами.

Евгений Степанищев (bolknote.ru) 2010

Комментарий для okakiy.livejournal.com:

Кстати, я тут подумал, выглядит мой пример, наверное, очень страшно, вот так можно короче:

gc access.log | ?{$_ -like ’*GET /tratata*’} | %{$_.Split()[1]} | sort -u

jankkhvej (jankkhvej.blogspot.com) 2010

Комментарий для Евгения Степанищева:

В PowerShell Get-Content (или алиас «cat») — это командлет (≈оператор), там язык имеет возможность более умно распорядиться ресурсами.

О! Вот что мне и надо было, спасибо!

Анонимный 2014

Здрасте :) Часто возникает вопрос с циклами вводимыми из текстовых файл типа таких:

for i in $(cat list_users.csv); do
done

как аналогичное делается в ps?

Евгений Степанищев 2014

Комментарий для Анонимный:

Здрасьте!

Тут вы используете антипаттерн бесполезный «cat» (https://en.wikipedia.org/wiki/Cat_(Unix)#UUOC_(Useless_Use_Of_Cat)), выше в комментариях об этом писали, этого можно избежать, например, так:

while read line; do
echo $line
done < list_users.csv

На Повершелле аналог может выглядеть, например, так (в отличие от Баша, cat тут не внешняя программа, а командлет, алиас Get-Content) :

cat list_users.csv | %{
…команды…
}

Я использую короткий синтаксис, но есть и более наглядный, посмотрите в руководстве. Было бы неплохо его вам вообще почитать, чтобы не задавать такие тривиальные вопросы.