извлечение подстроки из результата grep

11165
user17245

Учитывая файл журнала, я обычно делаю что-то вроде этого:

grep 'marker-1234' filter_log 

Какая разница в использовании «» или «» или ничего в шаблоне?

Приведенная выше команда grep выдаст много тысяч строк; что я хочу В этих строках обычно есть одна порция данных, которую я ищу. Иногда я использую awk для распечатки полей, которые мне нужны. В этом случае формат журнала изменяется, я не могу полагаться исключительно на позицию, не говоря уже о том, что фактические зарегистрированные данные могут сдвинуть позицию вперед.

Чтобы сделать это понятным, допустим, что в строке журнала содержался IP-адрес, и это было все, что мне было нужно, так что позже я могу передать его для сортировки и уникальности и получить подсчет количества.

Примером может быть:

2010-04-08 some logged data, indetermineate chars - [marker-1234] (123.123.123.123) from: foo@bar.example.com to bar@foo.example.com [stat-xyz9876] 

Первая команда grep даст мне много тысяч строк, подобных приведенным выше, оттуда я хочу передать это чему-то, возможно sed, что может извлечь шаблон изнутри и напечатать только шаблон.

Для этого примера достаточно использовать IP-адрес. Я старался. Разве sedне в состоянии понять [0-9] . как шаблон? Я должен был [0-9] [0-9] [0-9]. что дало странные результаты, пока весь шаблон не создан.

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

Спасибо вам всем.

4
Это звучит очень тесно связанным с программированием, даже простые команды bash, такие как * grep * и * awk *, на мой взгляд, лучше отвечают на stackoverflow. Josh K 14 лет назад 0
@Josh: У SU есть много воинов командной строки linux, которые могут решить этот вопрос, и это приветствуется. это может быть один из тех вопросов, которые подходят для любого сайта, так что это действительно вопрос для автора. quack quixote 14 лет назад 0
Я немного подумал, и, честно говоря, я не знал, где это разместить. Я выбрал названия сайтов, полагая, что SO - это более общий термин, а SU - более тип админского типа. Я считаю, что самый быстрый сценарий оболочки связан с администратором. Конечно, вы попадаете в большие эксклюзивные проекты tcl или bash по той или иной причине, и в этом случае я бы ограничил их связью с программированием и публикацией в SO. Это было больше одного лайнера, и SU казался хорошим домом. Извините, если я разместил сообщение не в том месте, но в некоторых случаях оно выглядит серым. user17245 14 лет назад 0
@allentown: на самом деле Server Fault - это скорее админ; Super User - это больше для конечного пользователя. (но для конечных пользователей опытных пользователей.) В любом случае, этот вопрос, вероятно, приветствуется на любом из SO / SF / SU. вы уже приняли ответ, поэтому, если вы удовлетворены, вы можете назвать его готовым. или, если вы хотите, мы можем перенести его в SO / SF; просто отметьте это для модератора и сообщите нам, куда отправить. Спасибо! quack quixote 14 лет назад 0
@ Quack: Хорошо, я просто думал, что там можно найти лучший ответ, однако кажется, что он уже найден. Josh K 14 лет назад 0

4 ответа на вопрос

7
Chris S

Я не знаю, на какой ОС вы работаете, но во FreeBSD 7.0+ grep имеет -oвозможность вернуть только ту часть, которая соответствует шаблону. Чтобы ты мог
grep "marker-1234" filter_log | grep -oE "[0-9]\.[0-9]\.[0-9]\.[0-9]"

Возвращает список только IP-адресов из 'filter_log "...

Это работает в моей системе, но, опять же, я не знаю, что поддерживает ваша версия grep.

Я думаю, что все ответы здесь являются отличными способами изучения и достижения конечного результата с тем же ответом. Мне особенно нравится этот, так как он легко запоминается и представляет собой трубу, объединяющую несколько команд grep. В Mac OS X у меня, кажется, есть опция -o, и, конечно, я часто использую опцию -E. Спасибо за ваш ответ user17245 14 лет назад 0
3
user31894

Вы можете сделать все это всего за одну awkкоманду. Нет необходимости использовать какие-либо другие инструменты

$ awk '/marker-1234/ }' file (123.123.123.123) 
Спасибо, это работает, awk иногда может немного повредить твою голову, но я привыкаю к ​​FOO .... один аспект лайнера быстрых вещей в оболочке. Очень могущественный. user17245 14 лет назад 0
2
Dennis Williamson

Вы можете сократить второй grepнемного так:

grep -Eo '([0-9]\.)[0-9]' 

Чтобы ответить на ваш первый вопрос, двойные кавычки позволяют оболочке выполнять различные действия, такие как расширение переменных, но защищают некоторые метасимволы от необходимости экранирования. Одинарные кавычки не позволяют оболочке выполнять эти расширения. Без кавычек оставляет вещи широко открытыми.

$ empty="" $ text1="some words" $ grep $empty some_file (It seems to hang, but it's just waiting for input since it thinks "some_file" is  the pattern and no filename was entered, so it thinks input is supposed to come from standard input. Press Ctrl-d to end it.) $ grep "$empty" some_file (The whole file is shown since a null pattern matches everything.) $ grep $text1 some_file grep: words: No such file or directory some_file:something some_file:some words (It sees the contents of the variable as two words, the first is seen as the  pattern, the second as one file and the filename as a second file.) $ grep "$text1" some_file some_file:some words (Expected results.) $ grep '$text1' some_file (No results. The variable isn't expanded and the file doesn't contain a string that consists of literally those characters (a dollar sign followed by "text1")) 

Вы можете узнать больше в разделе "QUOTING" man bash

Отлично, пишите, спасибо. Мне нужно лучше разобраться в этом с регадой к IFS, я был довольно одержим этим на днях, но сумел заставить IFS играть хорошо. Это ужасная вещь, когда вы установили IFS и забыли об этом, удивительно, что wtf продолжается в течение часа. user17245 14 лет назад 0
Рекомендуется всегда сохранять значение `IFS` и восстанавливать его как можно скорее:` saveIFS = "$ IFS"; КСФ = ""; сделай что-нибудь; IFS = "$ saveIFS"; do_other_stuff` Dennis Williamson 14 лет назад 0
+1 Хороший вызов для регулярных выражений, я не пользуюсь им много, поэтому я склонен быть немного неэффективным. Chris S 14 лет назад 0
1
Jennifer

Посмотрите на xargsкоманду. Вы должны быть в состоянии сделать что-то вроде:

grep 'marker-1234' filter_log | xargs grep "(" | вырезать -c1-15

Это может быть не совсем так, но xargsэто команда, которую вы хотите использовать