Архив за Март 2008

Про mod_rewrite, снова

в руководстве по apache видимо не зря пишут, что mod_rewrite — это сплошное шаманство…

искал сегодня весь вечер решение такой задачи:
пусть у нас есть на web-сервере странички
http://serv.qu/page1.html
http://serv.qu/page2.html
и т.д.
нужно, чтобы их содержимое было доступно по адресам
http://serv.qu/page1
http://serv.qu/page1/
с первым адресом все относительно просто, а вот со вторым, из-за слэша в конце, засада… В результате плясок с бубном выкристаллизовалось такое решение
во-первых отключаем MultiViews опцией Options -MultiViews
далее в .htaccess пишем
RewriteCond     %{REQUEST_URI}          ^(.*)/$
RewriteCond     %{REQUEST_FILENAME}     !-d
RewriteRule     ^(.*)$                  %1              [R=301,L]
(то есть, при наличии слэша в конце запроса и отсутствии такой директории на диске, перенаправляем на адрес без слэша в конце) RewriteCond     %{REQUEST_URI}          !^.*/$
RewriteCond     %{REQUEST_FILENAME}     !-f
RewriteRule     ^(.*)$                  $1.html         [L]
(а здесь уже проверяем, что если такого файла нет, то значит к нему надо добавить .html)

А если оставить MultiViews включенными — не работает, не знаю почему…

Сортировка по журналам LJ

Если подписаться на комментарии в ЖЖ, то приходящие письма имеют очень удобное для сортировки поле X-Lj-Journal, например "X-Lj-Journal: ru_debian". С помощью вот такого набора правил для procmail можно разложить их по полочкам

LJFOLDER=lj

:0
* ^From.*lj_notify.livejournal.com
{
  :0 Wic
  * ? test ! -d $LJFOLDER
  | mkdir $LJFOLDER

  :0 h
  LJJOURNAL=| formail -xX-Lj-Journal: | cut -c 2-

  :0
  ${LJFOLDER}/${LJJOURNAL}/
}

Для "X-Lj-Journal: ru_debian" получим папку "lj/ru_debian" в формате Maildir.

про конвертер данных II

Решил довести таки предыдущюю запись до логического конца. Итак, на следующей “итерации” мы переносим разбиение строк на столбцы к операции считывания данных и записываем в более питонистом стиле (то есть без lambda)

# считываем и разбиваем на столбцы
data = [x.split() for x in open(input_file, 'r').readlines()]
# конвертируем
data = [x+"  %4.2f\n"%((float(y)-32)/1.8) for (x,y) in data]
# записываем результат
open(output_file, 'w').writelines(data)

PS: ну а самый правильный инструмент для подобных задач, конечно же, awk
cat input.dat | awk '{print $1 "  " ($2-32)/1.8}' > output.dat

про конвертер данных

в свое время, знакомство с haskell отставило неизгладимый след в моем подходе к написанию программ :). Вот здесь обсуждают небольшой конвертер, который я переписал бы так

#!/usr/bin/env python
import sys, math

try:
    input_file = sys.argv[1];  output_file = sys.argv[2]
except:
    print "Usage:",sys.argv[0], "infile outfile"
    sys.exit(1)

ifile = open(input_file, 'r')
data = ifile.readlines()
ifile.close()

def convert_f_to_c(y):
    zz=(y-32)/1.8
    return zz

data = map(lambda (a,b):
           "%g  %4.2f\n" % (float(a),  convert_f_to_c(float(b))),
           map(lambda x: x.split(), data))

ofile = open(output_file, 'w')
ofile.writelines(data)
ofile.close()

Впрочем, этот код можно ещё упростить. Во-первых, совсем необязательно конвертировать первый столбец “строка” → “вещ. число” → “строка”, во-вторых, отдельную функцию convert_f_to_c перевода из Фарангейтов в Цельсии заменим на лямбду и получится

#!/usr/bin/env python
import sys, math

try:
    input_file = sys.argv[1];  output_file = sys.argv[2]
except:
    print "Usage:",sys.argv[0], "infile outfile"
    sys.exit(1)

ifile = open(input_file, 'r')
data = ifile.readlines()
ifile.close()

data = map(lambda (a,b):
           "%s  %4.2f\n" % (a,  (lambda f: (f-32)/1.8)(float(b))),
           map(lambda x: x.split(), data))

ofile = open(output_file, 'w')
ofile.writelines(data)
ofile.close()

mod_rewrite и строка запроса

Нагуглил таки сегодня решение такой задачки:
вот такое правило
RewriteRule ^page1 /new_page/ [R=301,L]
запросы вида /page1?id=10 перенаправляет на /new_page/?id=10
а иногда нужно, чтобы параметры строки после ? не передавались при перенаправлении.
Как оказалось, решение заключалось в добавлении всего одного символа
RewriteRule ^page1 /new_page/? [R=301,L]

В официальной документации Apache этот трюк я не нашел, и в результате потратил кучу времени.