Як робити grep, виключаючи деякі шаблони?


84

Я хотів би знайти рядки у файлах із появою якогось шаблону та відсутністю якогось іншого шаблону. Наприклад, мені потрібно знайти всі файли / рядки, включаючи loomкрім gloom. Отже, я можу знайти за loomдопомогою команди:

grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)

Тепер я хочу шукати, loomвиключаючи gloom. Однак не вдалося виконати обидві наступні команди:

grep -v 'gloom' -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
grep -n 'loom' -v 'gloom' ~/projects/**/trunk/src/**/*.@(h|cpp)

Що я повинен зробити для досягнення своєї мети?

EDIT 1: Я маю на увазі, щоloomіgloomє послідовностями символів (не обов’язково словами). Отже, мені потрібно, наприклад,bloombergу виведенні команди і не потрібноungloomy.

EDIT 2: Є зразок моїх очікувань. Обидва наступні рядки знаходяться в командному виведенні:

Я зіткнувся з іконами, що нависли крізь завісу ладану.

Арті мрачно йде в похмурий день.

Обидва наступні рядки відсутні в командному виведенні:

Це похмуро - це жахливо - великі каламутні дурники про клоуди.

На південному заході навколо висотного залу пинтит


Ви шукаєте файли, які відповідають вашим критеріям рядків, що відповідають вашим критеріям?
Джуто

Я шукаю файли з рядками, що відповідають моїм критеріям. І я хочу побачити список усіх наборів ім'я файлу + номер відповідного рядка + сам відповідний рядок.
Ткацький верстат

Якби рядок був there is a loom in the gloom- ви б хотіли, щоб цей рядок був надрукований? Просто намагаючись зрозуміти, чи просто ви шукаєте рядки, де трапляється стан, крім того, що є частиною мороку, чи ви дійсно хочете виключити рядки, що містять морок, навіть коли ткацький верстат з’являється на своєму власному місці в іншому місці лінії. Опублікування деяких зразків вводу та очікуваних результатів допомогло б.
Ед Мортон,

Отже, ваше запитання справді How do I find lines containing the string "loom" where "loom" is not preceded by the letter "g"? Якби ви опублікували зразки вхідних даних та бажаних результатів, які б дуже допомогли. Відповідь на це питання міститься у відповідях нижче.
Ед Мортон,

1
@EdMorton - Так, ти маєш рацію - мені потрібні всі рядки, де це відбувається loomбез попереднього g. (Вибачте. Я почав коментувати вчора, але так і не закінчив. Випадково цей коментар було надіслано.)
Ткацький верстат

Відповіді:


102

Як щодо того, щоб просто прив’язати ланцюжки?

grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'

13
Вчасно. Працює ідеально. -v - це варіант виключення. Дякую
Раві Крішна P

2
З питання: Отже, мені потрібно, наприклад, bloombergу командному виведенні і не потрібно ungloomy. Якщо в одному рядку міститься "... і Bloomberg не сповідує перспективи ...", ви усунете цей рядок, але він потрібен (тому що, якщо містить bloomberg).
Джонатан Леффлер,

23

Ще одне рішення без ланцюжка grep:

egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*.@(h|cpp)

Між дужками ви виключаєте символ gперед будь-яким входженням loom, якщо loomце не перші символи рядка.


9

Трохи старий, але ну добре ...

Найголосніше рішення від @houbysoft не буде працювати, оскільки воно виключає будь-який рядок із "похмурістю", навіть якщо в ньому є "ткацький верстат". Відповідно до очікувань OP, нам потрібно включити рядки з "ткацьким верстатом", навіть якщо вони також містять "похмурість". Цей рядок повинен бути у вихідному файлі "Арти мрачно йде в похмурий день", але це буде виключено ланцюговим grep, як

grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'

Натомість приклад регулярного виразу egrep Bentoy13 працює краще

egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*.@(h|cpp)

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


8

Просто використовуйте awk, це набагато простіше, ніж grep, дозволяючи вам чітко виразити складні умови.

Якщо ви хочете пропустити рядки, що містять обидва loomі gloom:

awk '/loom/ && !/gloom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)

або якщо ви хочете їх надрукувати:

awk '/(^|[^g])loom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)

а якщо реальність така, то вам потрібні просто рядки, де саме воно loomвідображається як слово:

awk '/\<loom\>/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)

3
Подумайте, як би ви написали команду grep, щоб отримати рядки, які містять abcі defта ghiв будь-якому порядку. А тепер порівняйте це з awk '/abc/ && /def/ && /ghi/'. А тепер подумайте, як awk '/loom/ && !/gloom/'у відповідях на цій сторінці написано еквівалент grep .
Ед Мортон,

Я не дуже знайомий з awk, мабуть, є книги про цю команду самі по собі. Поки що у мене все добре з grep, можливо, одного дня я скажу те саме, що і ти. :)
Juto

2
awk - це СТАНДАРТНИЙ інструмент UNX (тобто доступний у ВСІХ установках UNIX) для обробки текстових файлів. Ось для чого це було придумано, і це дуже добре в цьому виходить. Якщо ви користуєтеся UNIX і аналізуєте текстові файли, навчіться awk з книги "Ефективне програмування Awk", третє видання, Арнольда Робінса. Існує невелика зміна парадигми, щоб перейти, пов’язану з condition { action }синтаксисом awks, але тоді це легкий бриз для тих, хто має будь-який досвід мови C або інший алгол.
Ед Мортон,

Бонус: вихід, як grep -Hn --color:awk '/loom/ && !/gloom/ { gsub(/loom/, color("1;31") "&" color(0)); print color(35) FILENAME color(36) ":" color(32) FNR color(36) ":" color(0) $0; }; function color(c) { return "\033[" c "m"; }'
клубок

6

-v є прапором "перевернутий сірник", тому трубопроводи - це дуже хороший спосіб:

grep "loom" ~/projects/**/trunk/src/**/*.@(h|cpp)| grep -v "gloom"


5

/ * Ви можете виглядати приблизно так?

grep -vn "gloom" `grep -l "loom" ~/projects/**/trunk/src/**/*.@(h|cpp)`

BACKQUOTES використовуються як дужки для команд, тому в цьому випадку з -lувімкненим кодом у BACKQUOTES буде повернено вам імена файлів, а потім за допомогою -vn робити те, що ви хотіли: мати імена файлів, номери ліній, а також фактичні рядки.

ОНОВЛЕННЯ Або за допомогою xargs

grep -l "loom" ~/projects/**/trunk/src/**/*.@(h|cpp) | xargs grep -vn "gloom"

Сподіваюся, що це допоможе. * /

Будь ласка, ігноруйте те, що я написав вище, це сміття.

grep -n "loom" `grep -l "loom" tt4.txt` | grep -v "gloom"

               #this part gets the filenames with "loom"
#this part gets the lines with "loom"
                                          #this part gets the linenumber,
                                          #filename and actual line

4

Ви можете використовувати grep -P(регулярний вираз perl), що підтримується negative lookbehind:

grep -P '(?<!g)loom\b' ~/projects/**/trunk/src/**/*.@(h|cpp)

Я додав \bдля меж слів.


2
Вам не потрібно зазирнути, \([^g]\|^\)працює. І це не виключає рядків з обома loomі gloom.
Кевін,

@Kevin: OP хоче знайти рядки з ткацьким верстатом, але not gloom.
anubhava

Точно так. Якщо в рядку є і те, і інше, він цього не хоче, але це все одно збігатиметься.
Кевін,

@Kevin: Це НЕ буде відповідати похмурості, але відповідатиме ткацькому станку (як хоче OP).
anubhava

З питання: Отже, мені потрібно, наприклад, bloombergу командному виведенні і не потрібно ungloomy. Отже, межі слів є непродуктивними.
Джонатан Леффлер,

3
grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'

З питання: Отже, мені потрібно, наприклад, bloombergу командному виведенні і не потрібно ungloomy. Якщо в одному рядку міститься "... і Bloomberg не сповідує перспективи ...", ви усунете цей рядок, але він потрібен (тому що, якщо містить bloomberg).
Джонатан Леффлер,

@JonathanLeffler "Мені потрібно знайти всі файли / рядки, включаючи ткацький верстат, за винятком тих, що мають напівтемрява."
Jiminion

3

Просто використовуйте! grep -vкілька разів.

Зміст файлу

[root@server]# cat file
1
2
3
4
5

Виключіть рядок або збіг

[root@server]# cat file |grep -v 3
1
2
4
5

Виключіть рядок або зрівняйте кратність

[root@server]# cat file |grep -v 3 |grep -v 5
1
2
4

0

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

grep -w 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)

1
З питання: Отже, мені потрібно, наприклад, bloombergу командному виведенні і не потрібно ungloomy. Я не думаю, що -wце рішення цієї загадки.
Джонатан Леффлер,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.