Я изучаю Linux, и у меня есть проблема, которую я, кажется, не могу решить самостоятельно. Вот:
grep строка из файла, который содержит 4 числа подряд, но не более 4.
Я не уверен, как подойти к этому. Я могу искать конкретные числа, но не их количество в строке.
1234a12345
ли отображаться строка как или нет?\b\d{4}\b
Ответы:
Есть два способа интерпретировать этот вопрос; Я рассмотрю оба случая. Возможно, вы захотите отобразить строки:
Например, (1) будет отображаться
1234a56789
, но (2) не будет.Если вы хотите отобразить все строки, которые содержат последовательность из четырех цифр, которая сама по себе не является частью более длинной последовательности цифр, один из способов:
Здесь используются регулярные выражения Perl , которые поддерживает Ubuntu
grep
( GNU grep )-P
. Это не будет соответствовать тексту, как12345
, и не будет соответствовать1234
или2345
которые являются его частью. Но это будет соответствовать1234
в1234a56789
.В Perl регулярные выражения:
\d
означает любую цифру (это короткий способ сказать[0-9]
или[[:digit:]]
).x{4}
соответствуетx
4 раза. ({
}
синтаксис не является специфичным для регулярных выражений Perl; он также присутствует в расширенных регулярных выражениях черезgrep -E
.) Так\d{4}
же как и\d\d\d\d
.(?<!\d)
является отрицательным утверждением нулевой ширины. Это означает «если не предшествует»\d
.(?!\d)
является отрицательным прогнозным утверждением нулевой ширины. Это означает «если не следовать»\d
.(?<!\d)
и(?!\d)
не сопоставлять текст вне последовательности из четырех цифр; вместо этого они будут (при использовании вместе) предотвращать сопоставление последовательности из четырех цифр, если она является частью более длинной последовательности цифр.Использование только упреждающего просмотра или упреждающего просмотра недостаточно, потому что самая правая или самая левая четырехзначная подпоследовательность все равно будет совпадать.
Одно из преимуществ использования проверочных и прогнозных утверждений заключается в том, что ваш шаблон соответствует только самим последовательностям из четырех цифр, а не окружающему тексту. Это полезно при использовании цветовой подсветки (с
--color
опцией).По умолчанию в Ubuntu каждый пользователь имеет
alias grep='grep --color=auto'
в своем~.bashrc
файле . Таким образом, вы получаете автоматическое выделение цвета, когда запускаете простую команду, начинающуюся сgrep
(это когда псевдонимы раскрываются), а стандартный вывод - это терминал (это то, что проверяет). Совпадения обычно выделяются красным оттенком (близким к ярко- красному ), но я выделил его жирным курсивом. Вот скриншот:--color=auto
И вы даже можете
grep
напечатать только соответствующий текст, а не всю строку, с помощью-o
:Альтернативный путь, без заглядывающих и заглядывающих утверждений
Однако, если вы:
grep
она не поддерживает-P
или иным образом не хочет использовать регулярное выражение Perl, и... тогда вы можете достичь этого с помощью расширенного регулярного выражения :
Это соответствует четырем цифрам и нецифровому символу - или началу или концу строки - их окружению. В частности:
[0-9]
соответствует любой цифре (например[[:digit:]]
, или\d
в регулярных выражениях Perl) и{4}
означает «четыре раза». Так[0-9]{4}
соответствует четырехзначная последовательность.[^0-9]
соответствует символам не в диапазоне от0
сквозной9
. Это эквивалентно[^[:digit:]]
(или\D
, в регулярных выражениях Perl).^
, когда он не отображается в[
]
скобках, соответствует началу строки. Точно так же$
соответствует концу строки.|
означает или и скобки для группировки (как в алгебре). Таким образом,(^|[^0-9])
соответствует началу строки или нецифровому символу, а($|[^0-9])
соответствует концу строки или нецифровому символу.Таким образом, совпадения происходят только в строках, содержащих четырехзначную последовательность (
[0-9]{4}
), которая одновременно:(^|[^0-9])
), и($|[^0-9])
).Если же , с другой стороны, вы хотите , чтобы отобразить все строки, содержащие последовательность из четырех цифр, но не содержат какой - либо последовательности более четырех цифр (даже тот , который отделен от другой последовательности только четыре цифры), то концептуально ваш Цель состоит в том, чтобы найти линии, которые соответствуют одному шаблону, но не другому.
Поэтому, даже если вы знаете , как сделать это с помощью одного шаблона, я предложил бы использовать что - то вроде Мэтта второго предложения,
grep
ИНГ для двух моделей отдельно.При этом вы не получаете никаких преимуществ от расширенных функций регулярных выражений Perl, поэтому вы можете предпочесть их не использовать. Но в соответствии с вышеприведенным стилем, вот сокращение решения Мэтта с использованием
\d
(и фигурные скобки) вместо[0-9]
:Так как она использует
[0-9]
, способ Мэтты более компактен - он будет работать на системах , гдеgrep
не поддерживают Perl регулярных выражений. Если вы используете[0-9]
(или[[:digit:]]
) вместо\d
, но продолжаете использовать{
}
, вы получите переносимость пути Мэтта более кратко:Альтернативный способ, с одним рисунком
Если вы действительно предпочитаете
grep
команду, котораяgrep
s, разделенные каналом , как указано выше)... тогда вы можете использовать:
В
-x
флаг маркиgrep
отображать только те строки , где целые матчи линии (а не любая строка , содержащая матч).Я использовал регулярное выражение Perl, потому что я думаю, что краткость
\d
и\D
значительно повысить ясность в этом случае. Но если вам нужно что-то переносимое в системыgrep
, которые не поддерживают-P
, вы можете заменить их на[0-9]
и[^0-9]
(или на[[:digit:]]
и[^[:digit]]
):Как работают эти регулярные выражения:
Посередине
\d{4}
или[0-9]{4}
соответствует одной последовательности из четырех цифр. У нас может быть более одного из них, но у нас должен быть хотя бы один.Слева
(\d{0,4}\D)*
или([0-9]{0,4}[^0-9])*
соответствует нулю или более (*
) экземпляров не более четырех цифр, за которыми следует не цифра. Нулевые цифры (т. Е. Ничего) - это одна возможность для «не более четырех цифр». Это соответствует (а) пустой строке или (б) любой строке, заканчивающейся нецифровой цифрой и не содержащей последовательности из более чем четырех цифр.Поскольку текст, находящийся непосредственно слева от центральной части
\d{4}
(или[0-9]{4}
), должен быть либо пустым, либо заканчиваться нецифровой цифрой, это препятствует тому, чтобы центральная часть\d{4}
совпала с четырьмя цифрами, имеющими еще одну (пятую) цифру слева от них.Справа
(\D\d{0,4})*
или([^0-9][0-9]{0,4})*
соответствует нулю или нескольким (*
) экземплярам нецифровой цифры, за которой следуют не более четырех цифр (которые, как и прежде, могут быть четырьмя, тремя, двумя, одной или даже вообще ни одной). Это соответствует (a) пустой строке или (b) любой строке, начинающейся с нецифровой цифры и не содержащей последовательности из более чем четырех цифр.Поскольку текст, находящийся непосредственно справа от центральной части
\d{4}
(или[0-9]{4}
), должен быть либо пустым, либо начинаться с нецифровой цифры, это препятствует тому, чтобы центральная часть\d{4}
соответствовала четырем цифрам, имеющим еще одну (пятую) цифру справа от них.Это гарантирует, что где-то присутствует последовательность из четырех цифр, и что нигде нет последовательности из пяти или более цифр.
Это не плохо или неправильно делать это таким образом. Но, возможно, наиболее важной причиной для рассмотрения этой альтернативы является то, что она разъясняет преимущества использования (или аналогичного) вместо этого, как предложено выше и в ответе Мэтта .
grep -P '\d{4}' file | grep -Pv '\d{5}'
Таким образом, ясно, что ваша цель состоит в том, чтобы выбрать строки, которые содержат одно, а не другое. Кроме того, синтаксис более прост (так что многие читатели / сопровождающие могут его быстрее понять).
источник
Это покажет вам 4 числа подряд, но не более
Обратите внимание, что ^ означает не
Есть проблема с этим, хотя я не уверен, как это исправить ... если число является концом строки, то оно не будет отображаться.
Эта более уродливая версия, однако, подойдет для этого случая.
источник
a12345b
, потому что он совпадает2345b
.Если
grep
не поддерживает регулярные выражения perl (-P
), используйте следующую команду оболочки:где
printf '[0-9]%.0s' {1..4}
будет производить 4 раза[0-9]
. Этот метод полезен, когда у вас есть длинные цифры, и вы не хотите повторять шаблон (просто замените его4
своим количеством цифр для поиска).Использование
-w
будет искать все слова. Однако, если вас интересуют буквенно-цифровые строки, такие как1234a
, добавьте[^0-9]
в конец шаблона, например,Использование
$()
в основном подстановка команд . Проверьте этот пост, чтобы увидеть, какprintf
повторяет шаблон.источник
Вы можете попробовать команду ниже, заменив
file
фактическое имя файла в вашей системе:Вы также можете проверить этот учебник для большего использования команды grep.
источник