Як я можу привчатись до того чи іншого (2 речі) у файлі?


38

У мене є файл, який має "тоді" і "є".

я можу

$ grep "then " x.x
x and then some
x and then some
x and then some
x and then some

і я можу

$ grep "there " x.x
If there is no blob none some will be created

Як я можу шукати обох за одну операцію? я намагався

$ grep (then|there) x.x

-bash: помилка синтаксису біля несподіваного маркера `('

і

grep "(then|there)" x.x
durrantm.../code
# (Nothing)

Відповіді:


54

Потрібно помістити вираз у лапки. Помилка, яку ви отримуєте, є результатом інтерпретації bash (як спеціального символу.

Також потрібно сказати grep, щоб використовувати розширені регулярні вирази.

$ grep -E '(then|there)' x.x

Без розширених регулярних виразів, доведеться бігти |, (і ). Зауважте, що ми тут використовуємо одинарні лапки. Bash спеціально обробляє нахили в подвійних лапках.

$ grep '\(then\|there\)' x.x

У цьому випадку групування не потрібне.

$ grep 'then\|there' x.x

Було б потрібно щось подібне:

$ grep 'the\(n\|re\)' x.x

3
Дивіться також grep $'then\nthere'і grep -e then -e there. Зверніть увагу, що \|BRE не є стандартним. Решта -. Bash обробляє зворотні косі спеціально в подвійних лапках тільки до ", $, \ , `і символ нового рядка.
Стефан Шазелас

1
Яка мета x.x?
alex

7

Просто швидке доповнення, у більшості ароматів є команда під назвою egrep, яка є просто грейпом з -E. Мені особисто подобається набагато краще набрати

egrep "i(Pod|Pad|Phone)" access.log

Чим використовувати grep -E


2

Дані, задокументовані відповідно до "РЕГУЛЯРНІ ВИРАЗИ" на (або, принаймні, моїй) сторінці "man", насправді є розширеними регулярними виразами;

grep розуміє три різні версії синтаксису регулярних виразів: "basic", "Extended" та "perl". У GNU grep немає різниці у доступній функціональності між базовими та розширеними синтаксисами. В інших реалізаціях основні регулярні вирази менш потужні. Наступний опис стосується розширених регулярних виразів; різниці для основних регулярних виразів підсумовуються згодом.

Але grep не використовує їх за замовчуванням - вам потрібен -Eперемикач:

grep "(then|there)" x.x

Тому що (зі сторінки чоловіка знову):

Основні та розширені регулярні вирази

У основних регулярних виразах мета-символи?, +, {, |, (І) втрачають своє особливе значення; замість цього використовуйте зменшені версії \ ?, +, {, \ |, (і та).

Тому ви також можете використовувати:

grep "then\|there" x.x

Оскільки дужки в цьому випадку зайві.


0

Елегантна простота Баша, схоже, загубиться на величезній сторінці чоловіка.

На додаток до відмінних рішень вище, я думав, що спробую дати вам шпаргалку щодо того, як баш розбирає та інтерпретує заяви . Потім, використовуючи цю дорожню карту, я розберу приклади, подані запитуючим, щоб допомогти вам краще зрозуміти, чому вони не працюють за призначенням.


Примітка: рядки сценарію оболонки використовуються безпосередньо. Введені рядки введення спочатку розширюються історією.

Кожна лінія bash спочатку токенізується , або іншими словами подрібнюється до того, що називається лексемами . (Токенізація відбувається перед усіма іншими розширеннями, включаючи дужку, тильду, параметр, команду, арифметику, процес, розбиття слів та розширення імені файлу.)

Тут лексема означає частину вхідного рядка, розділеного (обмеженого) одним із цих спеціальних мета-символів:

space,  - White space...
tab, 
newline,

‘<’,    - Redirection & piping...
‘|’, 
‘>’
‘&’,    - And/Both < | > | >>  .or.  &<file descriptor>

‘;’,    - Command termination

‘(’,    - Subshell, closed by -     ‘)’

Bash використовує багато інших спеціальних символів, але лише ці 10 видають початкові жетони.

Однак, оскільки ці мета-символи також іноді повинні використовуватися в токені, повинен бути спосіб позбавити їх особливого значення. Це називається втечею. Екранування здійснюється або процитувати рядки з одного або декількох символів (тобто 'xx..', "xx.."), або випереджаючи індивідуальний характер з задніми косими рисами, (тобто \x). (Це трохи складніше, ніж це, тому що цитати також потрібно цитувати, і тому, що подвійні цитати не цитують все, але це спрощення зробить поки що.)

Не плутайте баш-цитування з ідеєю цитування рядка тексту, як на інших мовах. Між цитатами в bash - це не рядки, а розділи рядка введення, у якому вийшли метасимволи, щоб вони не розмежовували лексеми.

Зауважте, важлива різниця між ', і ", але це вже на інший день.

Решта мета-символів, які не були розроблені, потім стають розділювачами лексем.

Наприклад,

$ echo "x"'y'\g
xyg

$ echo "<"'|'\>
<|>

$ echo x\; echo y
x; echo y

У першому прикладі є два жетони, отримані роздільником пробілу: echoі xyz.

Аналогічно у 2-му прикладі.

У третьому прикладі крапка з комою уникли, таким чином , є 4 жетони , отримані космічним роздільником, echo, x;, echo, і y. Перший жетон запускається як команда і бере наступні три лексеми як вхідні дані. Зауважте, 2-й echoне виконується.


Важливо пам’ятати, що спочатку bash шукає втеча символів ( ', "і, \), а потім шукає нерозміщені роздільники мета-символів у такому порядку.

Якщо не уникнути, то ці 10 спеціальних символів служать tokenрозмежувачами. Деякі з них також мають додаткове значення, але в першу чергу вони є розмежувачами лексем.


Який греп очікує

У наведеному вище прикладі Grep потрібні ці маркери, grep, string, filename.

Першою спробою питання було:

$ grep (тоді | там) xx

В цьому випадку (, )і |є неекрановані символи мета і тому служать для поділу входу в ці маркери: grep, (, then, |, there, ), і x.x. Grep хоче бачити grep, then|thereі x.x.

Друга спроба питання:

grep "(тоді | там)" xx

Це розмічає в grep, (then|there), x.x. Це можна побачити, якщо ви поміняєте grep на ехо:

відлуння "(тоді | там)" xx
(тоді | там) xx

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