Регулярное выражение, чтобы соответствовать SHA1 - PullRequest
34 голосов
/ 22 января 2009

Я пытаюсь сопоставить SHA1 в обычном тексте с регулярным выражением.

В идеале я хочу избегать совпадения слов.

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

Можно ли рассчитывать на наличие цифр?

Глядя на SHA1 в моем журнале коммитов - числа всегда появляются в первых 3 символах. Но это слишком коротко? Сколько символов SHA1 мне нужно рассмотреть, прежде чем я смогу предположить, что число появилось бы?

Это не должно быть на 100% точно - мне просто нужно соответствовать сокращенному SHA1 в 99% случаев.

Ответы [ 6 ]

64 голосов
/ 22 января 2009

Вы можете считать хэши SHA1 абсолютно случайными, так что это сводится к вероятности. Вероятность того, что данная цифра не является числом, равна 6/16 или 0,375. Вероятность того, что все три цифры SHA1 не являются числами, составляет 0,375 ** 3 или 0,0527 (5% иша). В шести цифрах это снова уменьшается до 0,00278 (0,2%). При пяти цифрах вероятность того, что все буквы упадут ниже 1% (вы сказали, что хотите найти совпадение в 99% случаев).

Легко создать регулярное выражение, которое всегда соответствует значениям SHA1:

\b[0-9a-f]{5,40}\b

Тем не менее, это может также соответствовать идеально хорошим пятибуквенным словам, таким как «добавленный» или «блеклый». В моем файле /usr/share/dict/words есть несколько шести буквенных слов, которые бы соответствовали: "accede", "beaded", "bedded", "десятилетие", "deface", "efface" и "фасад" являются наиболее вероятными. В семи письмах есть только «дидед», который вряд ли появится в прозе. Все зависит от того, сколько ложных срабатываний вы можете терпеть и каковы вероятные слова, с которыми вы столкнетесь.

34 голосов
/ 22 января 2009

Что именно вы пытаетесь сделать? Вам не нужно анализировать какие-либо выходные данные git с помощью эвристики - вы всегда можете запросить именно те данные, которые вам нужны.

Если вы хотите сопоставить полное шестнадцатеричное представление суммы SHA1, попробуйте:

/\b([a-f0-9]{40})\b/

То есть слово, состоящее из 40 символов, которые представляют собой либо цифры, либо буквы от a до f.

Если у вас есть только несколько персонажей и вы не знаете, где они находятся, то вам не повезло. Является ли "e78fd98" сокращенным идентификатором коммита? Может быть, но как насчет "1234567"? Это идентификатор фиксации? Номер проблемного билета? Число, которое делает тест неудачным?

Без контекста вы не можете точно знать, что означают данные.

Чтобы ответить на ваш прямой вопрос, не существует свойства SHA1, которое сделало бы первые три символа (в шестнадцатеричной форме) цифрами. Вам просто повезло или, возможно, не повезло, в зависимости от того, как вы на это смотрите.

4 голосов
/ 22 января 2009

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

grep -o -E -e "[0-9a-f]{40}"

Будет соответствовать такому SHA1. Вам нужно будет перевести приведенное выше регулярное выражение с диалекта egrep на любой инструмент, который вы используете. Поскольку совпадение должно быть ровно 40 символов, я не думаю, что вы рискуете случайно подобрать слова. Я не знаю ни одного 40-символьного слова, состоящего только из букв от a до f.

редактирование:

Еще лучше: используйте Regex, чтобы соответствовать SHA1 , поскольку его решение включает проверку границ слов на обоих концах. Я упустил это из виду.

3 голосов
/ 02 июля 2010

Если у вас есть доступ к репо, вы можете использовать git cat-file -e, чтобы убедиться, что он представляет объект в репо. Это тоже очень быстро. Если вы хотите ограничить это только коммитами и тегами, вы можете использовать git cat-file -t, чтобы узнать тип объекта.

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

0 голосов
/ 30 января 2014

Я использую это в рубине. Он допускает короткий вариант ша (6 - 8 в случае столкновений) и полный ша длиной 40 символов.

\A(([0-9a-f]{40})|([0-9a-f]{6,8}))\z
0 голосов
/ 28 августа 2011

Для этого типа хэша: 43:A4:02:B7:B6:1D:89:86:C5:CE:AD:52:96:D9:2E:7B:64:98:45:6A:

/^[0-9A-F]{2}(:[0-9A-F]{2}){19}$/
...