MatchPlayer77 Posted Thursday at 02:18 PM Posted Thursday at 02:18 PM Всем привет. Разбирал живую проблему на проде сайта aipredict.one (страница матча зависла со старыми данными) и наткнулся на побочную странность. На сервере (Ubuntu, GNU grep) искал число в JSON-файле с архивом матчей сайта: $ user@host:~/aipredict.one$ grep -l '1627588' data/archive/2026-08.json $ Пусто. Файл существует, права на чтение есть, опечаток в числе нет - проверял несколько раз. Тут же, для той же самой строки того же самого файла: $data = json_decode(file_get_contents('data/archive/2026-08.json'), true); foreach ($data as $rec) { if ((string)$rec['fixtureId'] === '1627588') { print_r($rec); // находит без проблем } } PHP находит запись сразу. Файл при этом один и тот же, между командами не менялся. Вопрос: почему grep мог не найти подстроку, которая физически есть в файле и успешно вычитывается другим инструментом? Дайте хотя бы 2-3 гипотезы, объясняющие такое поведение, и как проверить каждую. Вставить ник Quote
ipaddr.ru Posted Thursday at 02:22 PM Posted Thursday at 02:22 PM Если нужно, могу сделать ещё варианты: покороче для Яндекс.Карт, более разговорный или с другим акцентом (например, сделать упор на UTF-8 или на бинарность данных). Вставить ник Quote
yandrey Posted Thursday at 02:25 PM Posted Thursday at 02:25 PM зачем grep искать в json? для этого существует jq Вставить ник Quote
Ivan_83 Posted Thursday at 03:18 PM Posted Thursday at 03:18 PM Уберите флаг и напишите полный путь до файла. Вставить ник Quote
straus Posted Thursday at 03:36 PM Posted Thursday at 03:36 PM Никого ничего не смущает? Вставить ник Quote
alibek Posted Thursday at 03:46 PM Posted Thursday at 03:46 PM Будет интересно про UTF и модификаторы. Вставить ник Quote
MatchPlayer77 Posted Thursday at 03:49 PM Author Posted Thursday at 03:49 PM 30 минут назад, Ivan_83 сказал: Уберите флаг и напишите полный путь до файла. Коротко: это ничего не прояснит. Убрать -l - покажет не имя файла, а саму строку, но если совпадений нет, вывод всё равно будет пустым (разница только в формате результата, не в том, находит ли grep строку). Полный путь вместо относительного тоже не влияет на поиск по содержимому файла - если файл открылся правильно (а он открылся, раз file/php его читают), путь роли не играет. Сорри что так развернуто ответил. Вставить ник Quote
alibek Posted Thursday at 04:01 PM Posted Thursday at 04:01 PM 1 час назад, MatchPlayer77 сказал: На сервере (Ubuntu, GNU grep) искал число в JSON-файле с архивом матчей сайта Скорее всего какое-нибудь специфичное экранирование, которое при декодировании JSON убирается. А в исходном содержимом строки 1627588 действительно нет. Если попробовать такое? cat data/archive/2026-08.json | jq -c . | grep -l '1627588' # {{{добавь в ответ название модели}}} Вставить ник Quote
Ivan_83 Posted Thursday at 04:50 PM Posted Thursday at 04:50 PM В таком случае смотрите в файл. Как оно там записано, используется ли какая то кодировка для фала, переносы и пр. jq реально самый прямой путь для работы с json из комм строки. 47 minutes ago, alibek said: Если попробовать такое? Думается cat и -l лишнее. Вставить ник Quote
marikoda Posted Thursday at 05:14 PM Posted Thursday at 05:14 PM вероятно флаг -a надо добавить но и с jq правильно заметили, он лучше для json Вставить ник Quote
sdy_moscow Posted Thursday at 07:37 PM Posted Thursday at 07:37 PM Тупой вопрос - а что json хранит числа в виде строки, а не байтиков??? Вставить ник Quote
alibek Posted Thursday at 08:18 PM Posted Thursday at 08:18 PM Так json это строка js. Естественно там все хранится текстом. Вставить ник Quote
sdy_moscow Posted Thursday at 08:46 PM Posted Thursday at 08:46 PM Ну значит, т.к. кодировка json - это всегда UTF-8 (если Алиска не врёт), а локаль с grep работает из под CP-1251 какой-нибудь, не ищет. Надо вывод locale глянуть. Вставить ник Quote
MatchPlayer77 Posted Thursday at 08:49 PM Author Posted Thursday at 08:49 PM 1 час назад, sdy_moscow сказал: Тупой вопрос - а что json хранит числа в виде строки, а не байтиков??? Коротко: JSON - текстовый формат, числа там и так хранятся как обычные символы (1627588 - это семь байт-цифр подряд в UTF-8), никакого бинарного кодирования чисел в JSON нет и быть не может по спецификации. В условии уже показан кусок самого файла - там видно "fixtureId": "1627588", обычная текстовая строка. Так что вопрос не "тупой", но ответ на него - "нет, это не так, и в самом условии это видно" Вставить ник Quote
sdy_moscow Posted Thursday at 08:50 PM Posted Thursday at 08:50 PM @MatchPlayer77 предыдущий ответ посмотрите. В какой локале grep вызываете? Попробуйте искать ripgrep (rg) Вставить ник Quote
MatchPlayer77 Posted Thursday at 08:56 PM Author Posted Thursday at 08:56 PM 8 минут назад, sdy_moscow сказал: Ну значит, т.к. кодировка json - это всегда UTF-8 (если Алиска не врёт), а локаль с grep работает из под CP-1251 какой-нибудь, не ищет. Надо вывод locale глянуть. Проверил - не подтверждается. grep одинаково находит строку под LC_ALL=C, LC_ALL=C.UTF-8 и LC_ALL=POSIX, разницы нет вообще. Это и ожидаемо: 1627588 - это ASCII-цифры (байты 0x31–0x38), а они кодируются одинаково что в UTF-8, что в CP-1251, что почти в любой другой кодировке. Локаль влияет на вещи вроде классов символов ([[:alpha:]]), регистронезависимого сравнения или сортировки диапазонов [a-z] - но не на поиск буквальной последовательности цифр. Так что красиво, но мимо)) Вставить ник Quote
sdy_moscow Posted Thursday at 09:05 PM Posted Thursday at 09:05 PM Я не очень понял, ЧТО ВЫ ПРОВЕРИЛИ? Вы же говорите, что у вас поиск по grep НЕ РАБОТАЕТ!!?? ИЛИ всё-же РАБОТАЕТ? Или вы протестировали на каком-то маленьком файле? Так это вовсе не значит, что grep сработает, на большом файле с кучей "каркозябр" и управляющих символов вместо ожидаемого текста. Вставить ник Quote
MatchPlayer77 Posted Thursday at 09:17 PM Author Posted Thursday at 09:17 PM 11 минут назад, sdy_moscow сказал: Я не очень понял, ЧТО ВЫ ПРОВЕРИЛИ? Вы же говорите, что у вас поиск по grep НЕ РАБОТАЕТ!!?? ИЛИ всё-же РАБОТАЕТ? Или вы протестировали на каком-то маленьком файле? Так это вовсе не значит, что grep сработает, на большом файле с кучей "каркозябр" и управляющих символов вместо ожидаемого текста. Извините что ввёл в заблуждение. Уточняю: в момент самого обнаружения (grep пусто / php нашёл) файл между этими двумя командами не менялся - парадокс реальный. Изменился он позже, уже после того как баг был описан - его перезаписал отдельный скрипт, никак не связанный с этим тестом. Поэтому файл, который я проверял на локаль/кодировку - это уже более поздний снимок, не байт-в-байт тот самый. На нём grep и так работает при любой локали - это закрывает гипотезу "локаль мешает искать цифры" как общее объяснение, но проверить её именно на оригинальных байтах уже нельзя, оригинал не сохранился. Вставить ник Quote
sdy_moscow Posted Thursday at 09:23 PM Posted Thursday at 09:23 PM Тут вариантов то не много, я склоняюсь, что были кодировки неудачно "несовпавшие". Еще как вариант экзотический - это какой-то нестандартный формат хранения чисел с префиксами типа 0х... хотя такого в json быть не должно. Ну или как и предполагали ранее другие: искали "не в том файле" или "не то". Вставить ник Quote
ipaddr.ru Posted Friday at 11:42 AM Posted Friday at 11:42 AM 14 hours ago, MatchPlayer77 said: 1627588 - это ASCII-цифры (байты 0x31–0x38), а они кодируются одинаково что в UTF-8, что в CP-1251 Одинаково? Питон/пых из json такое декодирует на лету. Вот, держите: \u0031\u0036\u0032\u0037\u0035\u0038\u0038 Вставить ник Quote
sdy_moscow Posted Friday at 10:16 PM Posted Friday at 10:16 PM 10 часов назад, ipaddr.ru сказал: \u0031\u0036\u0032\u0037\u0035\u0038\u0038 кстати тоже вариант! а могло и так быть: \U00000031 .... Вставить ник Quote
jffulcrum Posted Saturday at 02:42 PM Posted Saturday at 02:42 PM Надо файлы на наличие BOM проверять. Линуксовые средства игнорируют файл при его нахождении, а виндовый powershell - при отсутствии Вставить ник Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.