Kodomo

Пользователь

Unix, часть 2

Заходим на web-corpora.net.

ls
ls /srv/data/
ls /srv/data/ngrams/
ls /srv/data/ngrams/2012-1-gram/

И обнаруживаем там 1-граммы гугла. (Т.е. частотные списки словоформ).

Вспоминаем команды, которые мы знаем:

Есть ещё смешная команда tac – обратная к cat – вывести строки в обратном порядке. (И если уж туда пошло, то есть ещё rev – вывести строки в том же порядке, но буквы в строке в обратном порядке).

ls | tac

Посмотрим. что у нас в частотных списках есть.

ls /srv/data/ngrams/2012-1-gram/
tail /srv/data/ngrams/2012-1-gram/00001.csv
less /srv/data/ngrams/2012-1-gram/00001.csv

Первая колонка – словоформа или словоформа с разбором, далее пробел, вторая колонка – частота.

Будем искать слова с фе в середине.

egrep 'фе' /srv/data/ngrams/2012-1-gram/00001.csv
egrep 'фе' /srv/data/ngrams/2012-1-gram/00002.csv

По одному файлу можем.

egrep 'фе' /srv/data/ngrams/2012-1-gram/

egrep показывает содержимое файла, а не директории, директорию ему мы дать не можем.

egrep 'фе' /srv/data/ngrams/2012-1-gram/*.csv
egrep 'фе' /srv/data/ngrams/2012-1-gram/*.*
egrep 'фе' /srv/data/ngrams/2012-1-gram/*c*
egrep 'фе' /srv/data/ngrams/2012-1-gram/*

зато мы можем дать ему все имена файлов; правда, если мы ему даём больше одного имени файла на вход, он приписывает к каждой строке выдачи имя файла, от этого нужно избавиться

egrep 'фе' /srv/data/ngrams/2012-1-gram/* -o

Не помогло

cat /srv/data/ngrams/2012-1-gram/
cat /srv/data/ngrams/2012-1-gram/*   | egrep фе

cat тоже показывает содержимое файла, а не директории. Но если он собрал все файлы в один поток, то тот поток можно пофильтровать через egrep. Вообще, удобно потоковые преобразования текста начинать с cat.

cat /srv/data/ngrams/2012-1-gram/*   | 'egrep' 'фе'

Кавычки в шелле не играют смысловой роли, только обозначают, что между ними пробел и некоторые спецсимволы не играют особой роли. Лучше пользоваться одинарными, они экранируют от всего, кроме самих себя. Кавычками можно окружать и имя команды – это такой же аргумент, как и все.

cat /srv/data/ngrams/2012-1-gram/*   | egrep фе
cat /srv/data/ngrams/2012-1-gram/*   | egrep фе -c
cat /srv/data/ngrams/2012-1-gram/*   | egrep фе | wc

Можно выучить про десяток команд, какой у какой команды флаг про подсчёт объёма данных, но лучше пользоваться отдельной командочкой wc, которую мы можем пришлёпнуть к любой выдаче.

cat /srv/data/ngrams/2012-1-gram/*   | egrep фе | sort
cat /srv/data/ngrams/2012-1-gram/*   | egrep фе | sort | less

С сортировкой лучше.

cat /srv/data/ngrams/2012-1-gram/*   | egrep фе -i | wc
cat /srv/data/ngrams/2012-1-gram/*   | egrep фе -i | less

egrep -i игнорирует регистр букв. Как и в питоне параметр re.I у регулярных выражений. Как и в sed параметр /i после регулярных выражений (см. ниже), и в javascript он же. I всегда значит ignore case.

Задача всё-таки найти буквы фе в середине слова, нужно избавиться от находок, где фе по краям:

cat /srv/data/ngrams/2012-1-gram/*   | egrel .фе. -i | less
cat /srv/data/ngrams/2012-1-gram/*   | egrep .фе. -i | wc -l

Находок многовато. Если привести всё к нижнему регистру, мы сможем избавиться от лишнего.

tr не умеет работать с русскими кодировками, особенно, с уникодом. Зато с ним умеет работать sed, который, впрочем, не очень удобен для транслитерации:

cat /srv/data/ngrams/2012-1-gram/*   | egrep .фе. -i | sed -r 'y/АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ/абвгдеёжзийклмнопрстуфхцчшщъыьэюя/' | less
cat /srv/data/ngrams/2012-1-gram/*   | egrep .фе. -i | sed -r 'y/АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ/абвгдеёжзийклмнопрстуфхцчшщъыьэюя/' | sort | less

sed -r от слов stream text editor – очень мощный инструмент; в его основе маленький и очень простой язык программирования из двух понятий и десяти команд. Среди команд есть:

Можно доращивать наш pipeline и дальше, но давайте сохраним его результат в файл, чтобы не ждать каждый раз полминуты, пока прочитаются все файлы со всеми 1-граммами (их у гугла очень уж много).

cat /srv/data/ngrams/2012-1-gram/*   | egrep .фе. -i | sed -r 'y/АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ/абвгдеёжзийклмнопрстуфхцчшщъыьэюя/' | sort > fegrams.txt
ls
pwd
less fegrams.txt
tail fegrams.txt

Вроде получилось. Теперь хотим избавиться от дубликатов.

cat fegrams.txt | sed -r 's/[_A-Z]| //' | tail
cat fegrams.txt | sed -r 's/[_A-Z]*| //' | tail

Нет, так регулярные выражения не пишутся. Нам хочется взять всё от подчёркивания или пробела и до конца, и удалить, т.е. заменить на пустоту. Так и переведём же это в регулярные выражения дословно:

cat fegrams.txt | sed -r 's/[_ ].*//' | tail

Теперь можно избавиться от дублей (благо файл уже отсортирован, нам нет необходимости добавлять sort перед uniq):

cat fegrams.txt | sed -r 's/[_ ].*//' | uniq | less
cat fegrams.txt | sed -r 's/[_ ].*//' | uniq | tail

Лемматизируем, чтобы убрать дубли лемм:

mystem -h
cat fegrams.txt | sed -r 's/[_ ].*//' | uniq | mystem -e utf-8 -l -n | tail
cat fegrams.txt | sed -r 's/[_ ].*//' | uniq | mystem -e utf-8 -l -n | uniq | wc -l

Многовато. Да и там есть альтернативы разбор1|разбор2, надо от них избавиться:

cat fegrams.txt | sed -r 's/[_ ].*//' | uniq | mystem -e utf-8 -l -n | sort | uniq | sed -r 's/\|/\n/g' | wc -l

У sed после команды s/// вплотную после третьего слэша можно ставить флаги. Самые главные два:

Только после того, как мы разбили по | нужно снова сортировать и убирать дубли:

cat fegrams.txt | sed -r 's/[_ ].*//' | uniq | mystem -e utf-8 -l -n | sed -r 's/\|/\n/g' | sort | uniq | wc -l

Тогда уж уберём и бастардов:

cat fegrams.txt | sed -r 's/[_ ].*//' | uniq | mystem -e utf-8 -l -n | sed -r 's/\|/\n/g' | sort | uniq | egrep -v '[?]' | wc -l
cat fegrams.txt | sed -r 's/[_ ].*//' | uniq | mystem -e utf-8 -l -n | sed -r 's/\|/\n/g' | sort | uniq | egrep -v '[?]' | less

И вот ещё что. После лемматизации некоторые словоформы потеряли фе. Нужно снова проверить, что он остался:

cat fegrams.txt | sed -r 's/[_ ].*//' | uniq | mystem -e utf-8 -l -n | sed -r 's/\|/\n/g' | sort | uniq | egrep -v '[?]' | egrep '.фе.' | wc -l

А вот эта командочка очень помогла мне написать конспект. Да воспоможет в этом деле она и вам!

history | less

Flask, шаблоны: циклы и условия

В flask в шаблонах можно писать такие штуковины:

   1 abc
   2 {% for elem in items %}
   3 stuff with {{elem}} with stuff
   4 {% endfor %}
   5 end

Если мы это выполняем с items = [1,2,3], то получается:

   1 abc
   2 stuff with 1 with stuff
   3 stuff with 2 with stuff
   4 stuff with 3 with stuff
   5 end

То есть мы можем пройтись по списку, и для каждого элемента сгенерировать кусок шаблона. И для этого фактически никаких лишних телодвижений делать не нужно.

   1 <html>
   2   <head>...</head>
   3   <body>
   4     <form>...</form>
   5     <h1>Search results</h1>
   6     <ul>
   7       {% for line in result_lines %}
   8         <li>{{line}}</li>
   9       {% endfor %}
  10     </ul>
  11   </body>
  12 </html>

Аналогично существует конструкция if:

{% if ... %}
{% elif ... %}
{% else %}
{% endif %}

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