Використання зірки в grep


88

Я намагаюся шукати підрядок "abc" у певному файлі в linux / bash

Я також:

grep '*abc*' myFile

Це нічого не повертає.

Але якщо я:

grep 'abc' myFile

Він правильно повертає збіги.

Зараз це не проблема для мене. Але що, якщо я хочу спробувати більш складний рядок, скажімо

*abc * def *

Як би я це зробив, використовуючи grep?


3
Сам grep не підтримує символи підстановки на більшості платформ. Вам потрібно використовувати egrep, щоб використовувати символи підстановки. Оболонки мають інший синтаксис. "*" в оболонці - <будь-який рядок>. В egrep це оператор, який каже "0 багатьом із попередньої сутності". У grep це просто звичайний символ.
PanCrit

@PanCrit: *означає те саме в grep та egrep: це квантор, що означає нуль або більше попереднього атома. Це зовсім інша концепція, ніж узагальнюючі символи, використовувані оболонкою.
Алан Мур

Відповіді:


123

Зірочка - це просто оператор повторення , але вам потрібно сказати, що ви повторюєте. /*abc*/відповідає рядку, що містить ab та нуль або більше c (тому що другий * знаходиться на c; перший є безглуздим, оскільки немає чого його повторювати). Якщо ви хочете, щоб щось відповідало, вам потрібно сказати .*- крапка означає будь-який символ ( у межах певних вказівок ). Якщо ви хочете просто зіставити abc, ви можете просто сказати grep 'abc' myFile. Для більш складного збігу вам потрібно використовувати .*- grep 'abc.*def' myFileвідповідатиме рядку, який містить abc, за яким слід def з чимось за бажанням між ними.

Оновлення на основі коментаря:

*у регулярному виразі не зовсім те саме, що * у консолі. У консолі * є частиною конструкції glob і виконує лише функцію підстановки (наприклад, ls *.logбуде перераховано всі файли, які закінчуються на .log). Однак у регулярних виразах * є модифікатором, що означає, що він застосовується лише до символу або групи, що передує йому. Якщо ви хочете, щоб * у регулярних виразах діяв як підстановочний знак, вам потрібно використовувати, .*як уже згадувалося раніше, - крапка є символом підстановки, а зірка, змінюючи крапку, означає знайти одну або кілька крапок; тобто знайти одного або декількох персонажів.


1
Я думаю, що запитувач бентежить різницю між символами узагальнення оболонки та регулярними виразами. Я також підозрюю, що складнішим висловом буде: grep 'abc. * Def' (принаймні один пробіл присутній - можливо, два, як я писав).
Джонатан Леффлер

1
Насправді, опитувальник, схоже, не розуміє, що 'abc' - це не те саме, що '^ abc $' :-D
Масса

1
Так, я переплутався між глобусом та повними регулярними виразами. Я використовую * без крапки, щоб означати збіг із чим-небудь на оболонці.
Санбі

1
grep *означає "0 або більше", а grep за замовчуванням жадібний. Зверніть увагу , що в Grep основних регулярних виразів метасимволи ?, +, {, |, (, і )втрачають особливий сенс. Більше інформації: grep регулярні вирази
KrisWebDev

25

Крапковий символ означає збіг з будь-яким символом, отже, .*означає нуль або більше випадків будь-якого символу. Ви, мабуть, маєте на увазі використання, .*а не просто *.


Крапка - це метасимвол, який приймає будь-який символ, крім нових рядків .
Абхішек Камаль

12

«Знак зірки» має значення лише в тому випадку, якщо перед ним щось є. Якщо інструмента немає (у цьому випадку grep), це може просто сприймати його як помилку. Наприклад:

'*xyz'    is meaningless
'a*xyz'   means zero or more occurrences of 'a' followed by xyz

5
* Не є безглуздим; воно просто не має свого звичного значення (повторення), а означає "я зірка". Він відповідав би рядку, що містить зірку, за якою йдуть x, y та z.
Джонатан Леффлер

2
@Jonathan Це залежить від інструменту.


6

Вираз, який ви спробували, як, наприклад, той, що працює в командному рядку оболонки в Linux, називається " glob ". Глобальні вирази не є повними регулярними виразами , що grep використовує для вказівки рядків, які потрібно шукати. Ось (старий, маленький) пост про відмінності. Глобусні вирази (як у "ls *") інтерпретуються самою оболонкою.

Можна перекласти з глобусів в РЕ, але зазвичай це потрібно робити в голові.


1
Це лише глобус, якщо він аналізується оболонкою. Оскільки він зберігає рядок пошуку всередині одинарних лапок, оболонка залишає рядок у спокої та передає його цілим у argv grep.
Видимий упорядник

4

Ви не використовуєте регулярні вирази, тому має бути вибраний варіант grep fgrep, який буде поводитися так, як ви очікуєте.


2
fgrepзараз застаріла, grep -fзамість цього слід використовувати.
Прометей

1
Це "grep -F". Хороший ol 'fgrep може бути "застарілим", але вони не збираються його забирати, поки я ще живий.
Ендрю Білз,


1

Це може бути відповідь, яку ви шукаєте:

grep abc MyFile | grep def

Єдине, що ... він буде виводити рядки, де "def" стоїть перед АБО після "abc"


1

Це працювало для мене:

grep ". * $ {expr}" - із подвійними лапками, перед якими стоїть крапка. Де "вираз" - це будь-який рядок, який вам потрібен у кінці рядка.

Стандартний unix grep без додаткових перемикачів.


0

'*' працює як модифікатор попереднього елемента. Отже, "abc * def" шукає "ab", за яким слідує 0 або більше "c" з "def".

Напевно, вам потрібно «abc. * Def», який шукає «abc», за яким слід будь-яка кількість символів, за яким слід «def».

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.