Как использовать grep для поиска определенных слов в полях в базе данных с плоскими файлами? - PullRequest
2 голосов
/ 20 сентября 2009

Мне нужен этот вызов grep:

grep "field3=highland" data_file

чтобы вернуть оба результата с "field3 = highland", а также "field3 = chicago highland". Как я могу перепроектировать вызов grep для учета обоих сценариев?

Ответы [ 5 ]

2 голосов
/ 20 сентября 2009

ГЭ,

Мой совет - потратить значительно больше усилий на составление вашего вопроса.

Вы упоминаете "grep tool (Linux)" и "оператор SQL LIKE" ... в теме ... затем включаете откровенно неразборчивый вопрос, который, кажется, касается сопоставления двух различных вариантов образца строки ввода.

Вы получаете ответы, которые являются лишь предположениями о том, каким может быть ваш настоящий вопрос.

Я думаю, что вопрос что-то вроде:

"У меня есть данные, которые содержат несколько строк, таких как: field3=highland и field3=other stuff highland, и я хочу сопоставить все эти строки (отфильтровывая все остальное)."

Самое простое регулярное выражение, которое могло бы работать, было бы:

grep "field3=.*highland

... но это будет соответствовать таким вещам, как «field3 = highlands» и «field3 = thighland» и «myfield3 = ...» и т. Д. Также не будет соответствовать «field3 = ...» (с пробел между обозначением поля и знаком равенства).

Должен ли "field3" находиться в начале строки? Предполагается, что гористая местность должна быть закреплена в конце линии? Должно ли совпадать «highland», только если оно не является подстрокой в ​​более длинном «слове» (т. Е. Если символ перед «h» и после «d» не алфавитный)?

Существует множество вопросов о ваших ожидаемых входных данных и желаемых результатах ... которые будут иметь значительное влияние на виды регулярных выражений, которые будут совпадать или нет.

Ссылка на выражения SQL LIKE и ее токены% в основном бесполезна. По большей части токен% в выражении SQL LIKE эквивалентен регулярному выражению ". *". Если у вас есть фрагмент SQL, который работает (для того же диапазона входных данных), и вы пытаетесь найти функционально эквивалентное регулярное выражение ... тогда вам нужно время, чтобы вставить рабочее выражение SQL.

Также в этом вопросе нет ничего особенно специфичного для grep (Linux или иным образом). Было бы лучше отметить вопрос о регулярных выражениях.

В общем случае существует три или четыре общих абстракции для сопоставления текста с шаблонами: регулярные выражения (со многими вариантами), шаблоны "glob" и "wildmat" (оболочки и подобные MS-DOS) и выражения SQL LIKE.

Из этих регулярных выражений чаще всего используются программистами ... и они, безусловно, самые сложные. Они варьируются от самых старых простейших вариантов (как это было в исторических строковых редакторах UNIX ed, из которых первоначально было взято grep), до более мощных «расширенных» версий (типизированных egrep или grep -E) и выше. к безумно сложным «Perl-совместимым регулярным выражениям» (теперь широко используемым другими языками программирования в качестве библиотек PCRE).

Шаблоны шариков намного проще. Они поддерживают "подстановочные знаки" ... изначально просто? и * (любой отдельный символ или любое количество любых символов соответственно). Более поздние усовершенствования, которые поддерживаются современными оболочками и другими инструментами, включают поддержку классов символов (таких как [0-9] для любой цифры и [a-zA-Z] для любой буквы и т. Д.). Некоторые из них также поддерживают классы отрицательных символов.

Поскольку в шаблонах glob используются специальные символы (? И *), которые похожи на синтаксис регулярных выражений, хотя и для разных целей ... и поскольку они используют практически идентичный синтаксис для описания классов символов и их дополнений, шаблоны glob часто принимают за регулярные выражения. Когда я преподаю уроки по системному администрированию, мне обычно приходится обращать на это внимание, чтобы учащиеся «отучились» от небрежной терминологии, которая так распространена.

Старый MS-DOS «подстановочный знак» или «сопоставление с подстановочными знаками» можно рассматривать как вариант исходных шаблонов глобуса. Это только поддерживает? и * метасимволы ... с почти такой же семантикой, что и глобализация оболочки UNIX. Однако я советую не думать о них таким образом. Базовая семантика того, как командная строка MS-DOS обрабатывает аргументы, содержащие эти шаблоны, достаточно отличается от того, что представление о них как о «глобусах» является ловушкой. (Такая команда, как: COPY *.TXT *.BAK, совершенно разумна в MS-DOS, в то время как команда UNIX, такая как: cp *.txt *.bak, неправильна почти для любой разумной ситуации).

Очевидно, как я уже говорил выше, выражение SQL LIKE очень похоже на глобус UNIX. В большинстве базовых реализаций SQL LIKE есть только два «специальных» или «мета» символа% (аналог *) и _ (аналог?).

Обратите внимание на слова ласки здесь. Я не буду утверждать, что% равен так же, как глобус *, и что _ не равен так же, как глобус? персонаж. Могут быть некоторые угловые случаи (относительно того, как они могут пакетироваться в начале или конце строк, или рядом с пробелом и т. Д.). В разных реализациях SQL могут быть различия, и даже могут быть некоторые более жесткие версии библиотек UNIX / Linux fnmatch (globbing), которые могут изменить ситуацию, если вы попытаетесь использовать такие утверждения.

2 голосов
/ 20 сентября 2009

вы можете использовать * подстановочный знак

grep "field3=.*highland" data_file
1 голос
/ 20 сентября 2009

Если вы хотите получить все строки с 'field3 =', за которыми следуют любые символы, за которыми следует 'highland', вам необходимо:

grep 'field3=.*highland' data_file

'.' означает любой символ, а '*' означает ноль или более вхождений последнего шаблона. Таким образом, '.*' фактически является любой строкой, включая пустую.

1 голос
/ 20 сентября 2009
$ grep 'f=h\|f=c h' << eof
> f=c h
> f=h
> not
> going f= to
> match
> eof
f=c h
f=h
$ 

Или, если идея такова, что c может быть чем-то, возможно, что-то вроде:

$ grep 'f=.*h' 
0 голосов
/ 20 сентября 2009

Если вы хотите сопоставить третье поле строки с вашей строкой (вместо сопоставления с литералом "field3=highland"), grep не подходит для вас. В этом случае рассмотрим awk:

awk '$3=="highland" { print $0 }' <input file>

для точного соответствия или

awk '$3~".*highland.*" { print $0 }' <input file>

для сопоставления с регулярным выражением.

Обратите внимание, что awk предполагает пробел в качестве разделителя полей, но вы можете использовать "-F <field separator>", чтобы изменить его в командной строке, чтобы

awk -F : '$1~".*oo.*" {print $0}' /etc/passwd

извлекает корневую строку из файла паролей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...