Ещё о 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 $_}
31 декабря 2009 00:32

hshhhhh.name (hshhhhh.name)
31 декабря 2009, 10:50

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

okakiy.livejournal.com (okakiy.livejournal.com)
31 декабря 2009, 12:25

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

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

bolk (bolknote.ru)
31 декабря 2009, 13:39, ответ предназначен hshhhhh.name:

Он лучше.

bolk (bolknote.ru)
31 декабря 2009, 13:42, ответ предназначен okakiy.livejournal.com:

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

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

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

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

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

bolk (bolknote.ru)
31 декабря 2009, 14:39, ответ предназначен okakiy.livejournal.com:

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

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

bolk (bolknote.ru)
31 декабря 2009, 14:44, ответ предназначен 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)
31 декабря 2009, 16:20

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

http://en.wikipedia.org/wiki/Cat_(Unix)#Useless_use_of_cat

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

bolk (bolknote.ru)
31 декабря 2009, 16:40, ответ предназначен jankkhvej (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)
31 декабря 2009, 17:56

В 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 чего-то_там ?

bolk (bolknote.ru)
3 января 2010, 01:33, ответ предназначен jankkhvej (jankkhvej.blogspot.com):

Из чего мы делаем вывод, что языки программирования разные и странной было бы ожидать от PowerShell поведения bash.
Так что - вход у Sort-Object не может принять непосредственно контент из файла? Нельзя что ли написать Sort-Object < access.log
А чем операция „<“ существенно отличается от «cat file |»? Синтаксический сахар, не более. В версии 1.0, которую я более-менее знаю, такого сахара нет. Во второй версии, возможно, он есть. Но я не понимаю почему он принципиален.

bolk (bolknote.ru)
3 января 2010, 14:56, ответ предназначен jankkhvej (jankkhvej.blogspot.com):

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

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

bolk (bolknote.ru)
4 января 2010, 00:50, ответ предназначен okakiy.livejournal.com:

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

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

jankkhvej (jankkhvej.blogspot.com)
4 января 2010, 04:13, ответ предназначен bolk (bolknote.ru):

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

Анонимный (инкогнито)
29 июля 2014, 09:41

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

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

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

Евгений Степанищев (bolknote.ru)
29 июля 2014, 12:02, ответ предназначен Анонимному

Здрасьте!

Тут вы используете антипаттерн бесполезный «cat» (http://en.wikipedia.org/wiki/Cat_(Unix)#Useless_use_of_cat), выше в комментариях об этом писали, этого можно избежать, например, так:
while read line; do
echo $line
done < list_users.csv
На Повершелле аналог может выглядеть, например, так (в отличие от Баша, cat тут не внешняя программа, а командлет, алиас Get-Content) :
cat list_users.csv | %{
…команды…
}
Я использую короткий синтаксис, но есть и более наглядный, посмотрите в руководстве. Было бы неплохо его вам вообще почитать, чтобы не задавать такие тривиальные вопросы.

Ваше имя или адрес блога (можно OpenID):

Текст вашего комментария, не HTML:

Кому бы вы хотели ответить (или кликните на его аватару)