1. bash / Говнокод #17444

    −113

    1. 1
    find . -type f -exec perl -n -e 'print "{}:$.$_" if(/不聞不若聞之,聞之不若見之/);' {} \;

    А знаете почему? - Потому что Греп - говно.

    Запостил: wvxvw, 14 Января 2015

    Комментарии (57) RSS

    • Ты что китаец?
      Ответить
      • Нет, мне нужно разобрать около 8 лямов файлов созданых пользователями всего земного шара. И очень надо рассортировать по языкам.
        Ответить
    • В регулярке запятая не кошерная.
      Ответить
      • Я просто скопировал, что было. Ну, и гуглоперевод понравился (который вообще не в тему, но все же в тему).
        Ответить
        • А нормальный перевод фразы известен? Просто у гугла с восточными языками, как бы помягче выразиться... Пиздец, говно, и беспросветное уебанство, касательно не только переводчика, но и поиска.
          Ответить
          • Да, это народная пословица (только начало, весь текст: 不聞不若聞之,聞之不若見之,見之不若知之,知之不若行之;學至於行之而止矣), смысл примерно такой: "зло нужно убивать в зародыше", дословно что-то типа "пламя нужно гасить пока не разгорелось". Как Гугл дошел до запахов - я х.з. т.как китайский вообще никак.
            Ответить
    • какой-нибудь guess-language не справляется?
      Ответить
      • Ну мне не просто нужно угадать язык, мне нужно по категориям разложить, найти такие, где пользователь просто оставил текст из шаблона, а где что-то оригинальное написал. И вообще, это только подготовительный этап, дальше за этим идет лейбелинг, кластеринг и скайнет.
        Ответить
        • И всё это на баше и регулярках.
          Ответить
          • Реквестирую машинный перевод на регулярках. Это будет посильнее, чем гуглтранслейт.
            Ответить
          • Не, остальное - нумпай, но, прямо скажем, в смысле Юникода, Питон как-бы облажался, что второй, что третий: такой головняк, что лучше не связываться. Я так и не понял, на каком муйзыкальном инструменте нужно играть, чтобы он смог аргументы из командной строки распарсить в Юникод, а потом еще из них регулярку составить. Т.е. из файла я их могу прочитать в нужном формате, или просто вбить в интерпретатор, а вот sys.argsv - нивкакую.
            Ответить
            • $ cat 3.py
              #!/usr/bin/python3
              import sys
              print(sys.argv)
              $ ./3.py 不聞不若聞之
              ['./3.py', '不聞不若聞之']
              $ cat 2.py
              #!/usr/bin/python2
              import sys
              for a in sys.argv:
                  print a.decode('utf-8')
              $ ./2.py 不聞不若聞之
              ./2.py
              不聞不若聞之
              Что я делаю не так?

              P.S. Насчет регулярок - просто перегони в юникодные строки, с ними, емнип, всё норм.
              Ответить
              • Попробуй во втором: from future import print_function а потом print(type(sys.argsv[1])), print(sys.argsv[1])

                - У меня получалось, что либо type - str, либо если пытаться перекодировать, то получается полная херня, никак не совпадающая с юникодными кодпоинтами, либо я это вообще не могу распечатать, т.е. оно валится с ошибкой конвертации, либо при печати, либо при вызове format().
                Ответить
                • В локали же везде utf-8, можно про это не спрашивать?
                  # на втором питоне
                  print(type(sys.argv[1]))
                  print(sys.argv[1])
                  print(type(sys.argv[1].decode('utf-8')))
                  print(sys.argv[1].decode('utf-8'))
                  # выхлоп
                  $./2.py 不聞不若聞之
                  <type 'str'>
                  不聞不若聞之
                  <type 'unicode'>
                  不聞不若聞之
                  Ответить
            • Да вроде как ничего и не надо...
              #!/usr/bin/env python3
              # -*- coding: UTF-8
              # test.py
              
              import sys
              import re
              
              tests = ('野々原ゆずこ', '櫟井唯', '日向縁')
              regexp = '.*%s.*' % sys.argv[1]
              
              for test in tests:
                  match = re.match(regexp, test)
                  print('%s => %s' % (test, match.group(0) if match else None))

              ~ $ ./test.py 井
              野々原ゆずこ => None
              櫟井唯 => 櫟井唯
              日向縁 => None
              ~ $
              Ответить
              • #!/usr/bin/python
                from __future__ import print_function
                import sys
                import re
                
                for a in sys.argv:
                    print(u'pattern: {} non-unicode: {}'.format(
                        re.compile(a.decode('utf-8')).pattern, a))

                Вот это примерно воспроизводит ситуацию. Дословно не помню, код остался на работе. Вобщем смысл в том, что это головняк (особенно всилу того, что эти принты расставлены в библиотечном коде).
                Ответить
                • $ ./2.py 不聞不若聞之 ",不聞不若聞之" "афФыы" "Явфыу"
                  pattern: ./2.py non-unicode: ./2.py
                  pattern: 不聞不若聞之 non-unicode: 不聞不若聞之
                  pattern: ,不聞不若聞之 non-unicode: ,不聞不若聞之
                  pattern: афФыы non-unicode: афФыы
                  pattern: Явфыу non-unicode: Явфыу
                  $ python --version
                  Python 2.7.8
                  Единственно я поправил на re.compile(a.decode('utf-8')).pattern, a.decode('utf-8'))), иначе крашится из-за попытки раскодить a как ascii.
                  Ответить
                  • Ну так понятно, что в этом проблема. Но нужно будет еще на работе посмотреть, в чем именно была проблема. Просто в маленьком примере тяжело воспроизвести. Там еще и OptionParser учавствовал. Но мне кажется, что главной проблемой было то, что где-то нужно было одновременно распечатывать и юникодный текст и такой (а переводить его совсем не хочется, или тяжело, т.как он где-то в недрах нумпай / скайпай).
                    Ответить
                    • В третьем питоне, имхо, правильно поступили, убрав нахуй неявный каст из байтов в юникод и бросая вместо него исключение. Хоть питонисты и вопят, что дескать неудобно, теперь всегда явно декодировать, но это убрало одну из самых частых и дурацких проблем питона, когда уже на продакшене посреди какой-нибудь либы вылезает "'ascii' codec can't decode byte 0xd0 in position 0: ordinal not in range(128)".
                      Ответить
                      • Нифига не убрало. Я со всех сторон обмазался УТФ8, и тем не менее, этих ошибок меньше не стало. Кроме того, уебищные названия decode/encode - я вообще не знаю, что они значат: decode as / decode into / encode as / encode into - нихера не понятно ни в каком формате оригинал, ни во что превращается. Просто вообще не нужно было никаких encode/decode/unicode - только юникодные строки. Кто хочет неюникода - пусть страдает (использует самодельные списки и т.п.) вот от этого ошибок заметно поубавилось.

                        Говорю я это не гипотетически. В экшнскрипте, не смотря на кучу плохих решений, была внезапамятные времена возможность System.setCodepage() - работала глобально для всех строк. Но потом, что-то Макромедию осенило, и они это убрали, заменив все на Юникод, а для желающих поработать с однобайтными строками дали ByteArray. Который, конечно не работает ни с регулярками, ни с другими строковыми функциями. И однобайтные строки исчезли впринципе. Т.е. до сих пор есть люди, которые пишут на АС2 (который уже 10 лет как не развивается), но однобайтовых строк я не видел уже лет семь, а то и больше.
                        Ответить
                        • > уебищные названия decode/encode - я вообще не знаю, что они значат
                          Считаем юникодную строку нормальной, а все остальные - закодированными (в какую-то кодировку, лол). Тогда всё встаёт на свои места.

                          В третьем питоне по сути и есть массив байт (просто массив байт) и строка (юникодная, без конкретной кодировки). И они друг в друга тупо не кастуются без decode/encode. А вот во втором есть мультибайтовая строка (str), юникодная строка (unicode) и этот сраный автокаcт c кодеком ascii по-умолчанию (и вроде бы сменить его никак).
                          Ответить
                          • Вот не только нужно было массиву байт давать все те же методы, что и строке: а то получается, что кто-то написал програму, и даже ни разу не задумался о том, какие там строки, а потом выясняется, что они могут быть разными, и наступает жопа.
                            Они какогото хера добавили locale.getpreferredencoding() и sys.getfilesystemencoding() - своеобразный корейский рандом, который кто-то может использовать где-то, и потом в чужой програме все порушится. open() в таком случае будет себя вести неадекватно. Человек не должен писать codecs.open(file, encoding="utf-8") и т.п. херню, чтобы получить строку в формате по умолчанию. Тот, кто хочет приключений должен страдать, а не тот, кто хотел просто побыстрее сделать и забыть.
                            Ответить
                            • > Вот не только нужно было массиву байт давать все те же методы, что и строке
                              В третьем и не дают! И большая часть воплей со стороны питонистов как раз из-за того, что там далеко не все методы, которые есть у строки.
                              Ответить
                        • >Кроме того, уебищные названия decode/encode - я вообще не знаю, что они значат: decode as / decode into / encode as / encode into - нихера не понятно ни в каком формате оригинал, ни во что превращается.
                          Есть такое. Но в 3 появился необязательный параметр "кодировка" у str/bytes.

                          >Просто вообще не нужно было никаких encode/decode/unicode - только юникодные строки. Кто хочет неюникода - пусть страдает (использует самодельные списки и т.п.) вот от этого ошибок заметно поубавилось.
                          Поехавший, что предлагаешь на замену byte[]? Кстати, ты предлагаешь взять опыт жавы. Питон потихоньку к ней идет :)
                          Ответить
                      • >Хоть питонисты и вопят, что дескать неудобно
                        Это пхпитонисты.
                        Ответить
                    • Ну вот с аргпарсером написал пример:
                      #!/usr/bin/python
                      # coding: utf-8
                      from __future__ import print_function
                      import argparse
                      import re
                      
                      parser = argparse.ArgumentParser('Regex test')
                      parser.add_argument('--re', help='regular expression', required=True)
                      parser.add_argument('--s', help='string for matching', required=True)
                      
                      args = parser.parse_args()
                      
                      regex = re.compile(args.re.decode('utf-8'))
                      string = args.s.decode('utf-8')
                      match = regex.match(string)
                      if match:
                          print("Match: ")
                          for group in match.groups():
                              print(group)
                      else:
                          print("No match")
                      Вроде всё работает:
                      $ ./test.py --re "([А-Яа-я]+)" --s "хуй"
                      Match: 
                      хуй
                      $ ./test.py --re "不聞(不若)聞" --s "不聞不d若聞"
                      No match
                      $ ./test.py --re "不聞(不若)聞" --s "不聞不若聞"
                      Match: 
                      不若
                      Может какой-то косяк конкретно в numpy?
                      Ответить
                      • О, а, вот теперь попробуй, например с
                        PYTHONIOENCODING=latin-1 ./test.py --re "([А-Яа-я]+)" --s "хуй"
                        Ответить
                        • > PYTHONIOENCODING
                          Ну упадёт на print(group). Что в этом такого? Юзер приказал высрать русские буквы в latin-1, а они в latin-1 непредставимы. И остаётся или замести проблему под ковёр и вопросиков нахуярить, или исключение кинуть. ССЗБ короче. Как и вывод японских иероглифов, если в консоли cp1251.
                          Ответить
                          • Да зачем вообще эта опция? Я легко себе могу представить как кто-то ею воспользуется, чтобы пофиксить свою неработающую програму. Ведь мы же не переводим консоль в другую кодировку, а где-то незаметно для других меняем кодировку ввода для Питона.
                            Ответить
                            • > Да зачем вообще эта опция?
                              Скорее всего для интеграции с legacy программами. Например следующая программа в конвейере жрёт только koi8-r, или мы перенаправляем вывод в файл, и хотим cp1251. Спорно, конечно, тут iconv проще засунуть.

                              > кто-то ею воспользуется, чтобы пофиксить свою неработающую програму
                              И это его личная проблема. Он так и локаль может поставить latin1, а потом жаловаться, чего это русские буквы не выводятся.
                              Ответить
                              • Если он локаль поставит - то навредит всем програмам, а не только Питону. Тут же как бы Питон намекает: "проблемы? - просто смени кодировку ввода!"
                                Ответить
                      • в итоге, я нагнал на Питон. Во всем виновать find который портил агументы, которые передавал в exec.
                        Ответить
                        • А почему пёрл нормально принимает?
                          Ответить
                          • Потому что Перл я проверял дома :) Хз. на рабочем компе какой-то неправильный find.
                            Ответить
              • Кроме того, регулярки в Юникоде находят хз. что. Т.е. можно дать регулярку на русском, а оно будет находить испанские, польские, или даже арабские тексты. А может это мне с версией повезло, вобщем, хз. В любом случае это не удобно все время конвертировать из одного в другое (нахер вообще в 21м веке кодировки кроме УТФ8?).
                Ответить
                • > нахер вообще в 21м веке кодировки кроме УТФ8
                  Чтобы читать файлы, сгенеренные прогами 20го века. В третьем питоне аргументы сразу в юникоде, тащемта.
                  Ответить
                • > можно дать регулярку на русском
                  Регулярка точно юникодная была? Потому что регулярка r"[а-я]" (не путать с ur"[а-я]") парсится вообще хуй-пойми как. Что-то типа \xd0 диапазона от \xb0 до \xd1 и \x8f. Так что там запросто всякая хуйня попадёт. И да, искать такая регулярка будет побайтово, не посимвольно.
                  Ответить
                  • Ну так регулярка должна браться из командной строки, которую нужно переводить в юникод, и вот с этим и была лажа.
                    Ответить
                • Потому в третьем бидоне регулярки в том числе по умолчанию юникодные.
                  Ответить
                  • Вот только не надо про по умолчанию. По умолчанию они в выбраной локали. А это часто Юникод, но иногда, когда кому-то очень захочется - не Юникод.
                    Ответить
                    • Не путай, пожалуйста, юникод и utf-8.

                      Юникод, сам по себе, не имеет никакого байтового представления. Это просто коды символов (codepoint вроде бы называется). И записать в файл его нельзя, для этого нужен кодек, записывающий эти кодепоинты в какой-то кодировке (просто питон неявно подставляет какой-то по умолчанию).

                      А utf-8 - это одна из кодировок, отображающих байты <-> коды символов. От всяких уебанских кодировок типа cp1251 она отличается только одним - в ней представимы все символы юникода.

                      str() в utf-8 в питоне 2.х - НЕ ЮНИКОДНАЯ СТРОКА. Это надо написать в начале мана крупным шрифтом и заставлять всех питонистов повторять как заповедь по утрам... Юникодная строка в питоне 2.х unicode() и только unicode(). И ее литерал пишется как u"..." и ur"...".
                      Ответить
                      • О, да, я еще и про это забыл. Ну вот зачем этот зоопарк?
                        Ответить
                        • Юникод такой юникод :3

                          P.S. Благодаря юникоду длину строки теперь можно считать в:
                          - в кодепоинтах
                          - в глифах (ту же ё можно записать как джва кодепоинта - е + точки)
                          - в байтах (в какой-то конкретной кодировке, в разных - разная)
                          - в пикселях (если шрифт не моноширинный)
                          - в знакоместах (моноширинный шрифт консоли, всякие японские символы по 2 знакоместа)
                          Ответить
                          • Мне кажется, что Unicode придумал наш bormand. Уж слишком пунктуален bormand, когда речь заходит об Unicode...
                            Ответить
                      • Питонисты это и не путают. Ее литерал пишется как from __future__ import unicode_literals и b'' для байтов.
                        Ответить
                • если ты это про перл.

                  > Кроме того, регулярки в Юникоде находят хз. что.

                  перлу нужно сказать что у тебя юникод. по умолчанию старый добрый аскии/байнари.

                  смотри в `man perlrun` опцию `-C`. плюс `use utf8`. у меня это иногда работало.

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

                  > нахер вообще в 21м веке кодировки кроме УТФ8?

                  азиатов это жутко напрягает, потому что в утф8, у них все буквы 3 байта. местные кодировки - 2 байта. текстовые базы/прочее раздуваются в размере очень быстро. вот поэтому часто утф8 строной обходят.

                  ЗЫ а в decode/encode это они на самом деле дерьмо сделали. можешь попробовать еще на perlmonks спросить.
                  Ответить
                  • Не, это я про Питон. С Перлом я просто очень мало знаком, но меня очень порадовал тот факт, что написав что-то похожее на ОП (только с /\p{Cyrillic}/ например), я получил безо всяких мытарств и чтений нравоучительных статей о том как Питон 3 теперь стал еще лучше, я получил именно то, что и ожидал.
                    Ответить
                    • меня лично эти \p{blabla} напрягают. но похоже что тебе в самый раз...
                      Ответить
                    • > \p{Cyrillic}
                      Но ведь это не только русские буквы, но и вся остальная кириллица.
                      Ответить
                      • Ну так проще сначала разбить на кирилицу и не-кирилицу, а потом уже кирлицу на разные подгрупы, чем пытаться из общей кучи, где кирилицы примерно 1% выбирать разные ее варианты.
                        Ответить
                        • divide and conquer. правильная стратегия работы с большими объемами информации.

                          самое главное это искать большие легко-обрабатываемы куски и их как можно раньше обработать и выкидывать, что бы количество данных постепенно уменьшать.
                          Ответить
                  • > азиатов это жутко напрягает
                    А ведь юникод, в основном, ради них и арабов запиливали...

                    Зажрались они, имхо. Тот же текст на русском подлиннее будет, т.к. у нас слова не по 2 иероглифа.
                    Ответить
                    • > А ведь юникод, в основном, ради них и арабов запиливали...

                      Да. Но это было уже давно. Потом Юникод.орг начал все остальные языки туда тоже добавлять, включая мертвые и полумертвые, почему и вылезли из 2-х байтового диапазона.

                      (Я помню там какой-то почти мертвый иероглифический язык добавили из того же региона, которым никто почти и не пользуются. Местность нищая, писать умеют не многие (потому что язык долбанутый и недоразвитый), компов ни у кого нет - но зато 10+К символов в Юникод таблице для них добавили. Народ в те времена долго возмущался на эту тему. И как раз азиаты. Потому что Юникод после этого в 2 байта перестал помещается...)

                      > Тот же текст на русском подлиннее будет, т.к. у нас слова не по 2 иероглифа.

                      Для большинство разговорной речи айзеры пользуются фонетической записью. Я слышал что даже китайцы начали уже адаптироваться для SMS/текстинг, и правильными иероглифами пишется мало, а вместо этого используется только подмножество как суррогатный фонетический алфавит. (По принципу японских хираганы и катаканы).

                      Другими словами, я не думаю что большая разница там где-то будет по сравнению с русским. Во первых, во вторых, все большие русские базы которые я видел, все наповал пользуются win-1251. Да, потом конвертится в утф, но на диске лежит в win-1251.
                      Ответить
      • Кстати по поводу guess_language - Результаты совсем аховые. Украинский, например, он вообще не распознает. Почти половина русского - как болгарский. Кавказские разновидности (которые используют кириличный шрифт), которые даже и близко на русский не похожи распознает как русский. Вобщем, в регулярках сила.
        Ответить

    Добавить комментарий