$put_perv_real = "/home/www/dvakompa-ru/dopol/"; ?>
Намедни хабраюзер simpleadmin выложил довольно полезную заметку про grep. Дальше от автора:
Поэтому… Лето… Пятница… Немного поговорим о grep.
Зная местную публику и дабы не возникало излишних инсинуаций сообщаю, что всё нижеизложенное справедливо для
# grep --version | grep grep
grep (GNU grep) 2.5.1-FreeBSD
Это важно в связи с
# man grep | grep -iB 2 freebsd
-P, --perl-regexp
Interpret PATTERN as a Perl regular expression. This option is
not supported in FreeBSD.
Для начала о том как мы обычно grep'аем файлы.
Используя cat:
root@nm3:/ # cat /var/run/dmesg.boot | grep CPU:
CPU: Intel(R) Core(TM)2 Quad CPU Q9550 @ 2.83GHz (2833.07-MHz K8-class CPU)
Но зачем? Ведь можно и так:
root@nm3:/ # grep CPU: /var/run/dmesg.boot
CPU: Intel(R) Core(TM)2 Quad CPU Q9550 @ 2.83GHz (2833.07-MHz K8-class CPU)
Или вот так (ненавижу такую конструкцию):
root@nm3:/ #
Зачем-то считаем отобранные строки с помощью wc:
root@nm3:/ # grep WARNING /var/run/dmesg.boot | wc -l
3
Хотя можно:
root@nm3:/ # grep WARNING /var/run/dmesg.boot -c
3
Сделаем тестовый файлик:
И приступим к поискам:
Опция -w позволяет искать по слову целиком:
root@nm3:/ # grep -w 'seven' test.txt
seven eight one eight three
sixteen seventeen eighteen seven
twenty seven
А если нужно по началу или концу слова?
root@nm3:/ # grep '\
root@nm3:/ # grep 'seven\>' test.txt
seven eight one eight three
sixteen seventeen eighteen seven
twenty seven
twentyseven
Стоящие в начале или конце строки?
root@nm3:/ # grep '^seven' test.txt
seven eight one eight three
root@nm3:/ # grep 'seven$' test.txt
sixteen seventeen eighteen seven
twenty seven
twentyseven
Хотите увидеть строки в в окрестности искомой?
root@nm3:/ # grep -C 1 twentyseven test.txt
#comment UP
twentyseven
#comment down
Только снизу или сверху?
root@nm3:/ # grep -A 1 twentyseven test.txt
twentyseven
#comment down
root@nm3:/ # grep -B 1 twentyseven test.txt
#comment UP
twentyseven
А ещё мы умеем так
root@nm3:/ # grep "twenty[1-4]" test.txt
twenty1
twenty3
И наоборот исключая эти
root@nm3:/ # grep "twenty[^1-4]" test.txt
twenty seven
twentyseven
twenty5
twenty7
Разумеется grep поддерживает и прочие базовые квантификаторы, метасимволы и другие прелести регулярок
Пару практических примеров:
root@nm3:/ # cat /etc/resolv.conf
#options edns0
#nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 77.88.8.8
nameserver 8.8.4.4
Отбираем только строки с ip:
root@nm3:/ # grep -E "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}" /etc/resolv.conf
#nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 77.88.8.8
nameserver 8.8.4.4
Работает, но так симпатичнее:
root@nm3:/ # grep -E '\b[0-9]{1,3}(\.[0-9]{1,3}){3}\b' /etc/resolv.conf
#nameserver 127.0.0.1
nameserver 8.8.8.8
nameserver 77.88.8.8
nameserver 8.8.4.4
Уберём строку с комментарием?
root@nm3:/ # grep -E '\b[0-9]{1,3}(\.[0-9]{1,3}){3}\b' /etc/resolv.conf | grep -v #
nameserver 8.8.8.8
nameserver 77.88.8.8
nameserver 8.8.4.4
А теперь выберем только сами ip
root@nm3:/ # grep -oE '\b[0-9]{1,3}(\.[0-9]{1,3}){3}\b' /etc/resolv.conf | grep -v #
127.0.0.1
8.8.8.8
77.88.8.8
8.8.4.4
Вот незадача… Закомментированная строка вернулась. Это связано с особенностью обработки шаблонов. Как быть? Вот так:
root@nm3:/ # grep -v # /etc/resolv.conf | grep -oE '\b[0-9]{1,3}(\.[0-9]{1,3}){3}\b'
8.8.8.8
77.88.8.8
8.8.4.4
Здесь остановимся на инвертировании поиска ключом -v
Допустим нам нужно выполнить «ps -afx | grep ttyv»
root@nm3:/ # ps -afx | grep ttyv
1269 v1 Is+ 0:00.00 /usr/libexec/getty Pc ttyv1
1270 v2 Is+ 0:00.00 /usr/libexec/getty Pc ttyv2
1271 v3 Is+ 0:00.00 /usr/libexec/getty Pc ttyv3
1272 v4 Is+ 0:00.00 /usr/libexec/getty Pc ttyv4
1273 v5 Is+ 0:00.00 /usr/libexec/getty Pc ttyv5
1274 v6 Is+ 0:00.00 /usr/libexec/getty Pc ttyv6
1275 v7 Is+ 0:00.00 /usr/libexec/getty Pc ttyv7
48798 2 S+ 0:00.00 grep ttyv
Всё бы ничего, но строка «48798 2 S+ 0:00.00 grep ttyv» нам не нужна. Используем -v
root@nm3:/ # ps -afx | grep ttyv | grep -v grep
1269 v1 Is+ 0:00.00 /usr/libexec/getty Pc ttyv1
1270 v2 Is+ 0:00.00 /usr/libexec/getty Pc ttyv2
1271 v3 Is+ 0:00.00 /usr/libexec/getty Pc ttyv3
1272 v4 Is+ 0:00.00 /usr/libexec/getty Pc ttyv4
1273 v5 Is+ 0:00.00 /usr/libexec/getty Pc ttyv5
1274 v6 Is+ 0:00.00 /usr/libexec/getty Pc ttyv6
1275 v7 Is+ 0:00.00 /usr/libexec/getty Pc ttyv7
Некрасивая конструкция? Потрюкачим немного:
root@nm3:/ # ps -afx | grep "[t]tyv"
1269 v1 Is+ 0:00.00 /usr/libexec/getty Pc ttyv1
1270 v2 Is+ 0:00.00 /usr/libexec/getty Pc ttyv2
1271 v3 Is+ 0:00.00 /usr/libexec/getty Pc ttyv3
1272 v4 Is+ 0:00.00 /usr/libexec/getty Pc ttyv4
1273 v5 Is+ 0:00.00 /usr/libexec/getty Pc ttyv5
1274 v6 Is+ 0:00.00 /usr/libexec/getty Pc ttyv6
1275 v7 Is+ 0:00.00 /usr/libexec/getty Pc ttyv7
Также не забываем про | (ИЛИ)
root@nm3:/ # vmstat -z | grep -E "(sock|ITEM)"
ITEM SIZE LIMIT USED FREE REQ FAIL SLEEP
socket: 696, 130295, 30, 65, 43764, 0, 0
ну и тоже самое, иначе:
root@nm3:/ # vmstat -z | grep "sock\|ITEM"
ITEM SIZE LIMIT USED FREE REQ FAIL SLEEP
socket: 696, 130295, 30, 65, 43825, 0, 0
Ну и если о использовании регулярок в grep'e помнят многие, то об использовании POSIX классов как-то забывают, а это тоже иногда удобно.
POSIX
Отберём строки с заглавными символами:
root@nm3:/ # grep "[[:upper:]]" test.txt
#comment UP
Ну и ещё пару трюков для затравки.
Первый скорее академичный. За лет 15 ни разу его не использовал:
Нужно из нашего тестового файла выбрать строки содержащие six или seven или eight:
Пока всё просто:
root@nm3:/ # grep -E "(six|seven|eight)" test.txt
seven eight one eight three
sixteen seventeen eighteen seven
sixteen seventeen eighteen
twenty seven
twentyseven
А теперь только те строки в которых six или seven или eight встречаются несколько раз. Эта фишка именуется Backreferences
root@nm3:/ # grep -E "(six|seven|eight).*\1" test.txt
seven eight one eight three
sixteen seventeen eighteen seven
Ну и второй трюк, куда более полезный. Необходимо вывести строки в которых 504 с обеих сторон ограничено табуляцией.
Ох как тут не хватает поддержки PCRE…
Использование POSIX-классов не спасает:
root@nm3:/ # grep "[[:blank:]]504[[:blank:]]" test.txt
one 504 one
one 504 one
one 504 one
На помощь приходит конструкция [CTRL+V][TAB]:
root@nm3:/ # grep " 504 " test.txt
one 504 one
Что ещё не сказал? Разумеется, grep умеет искать в файлах/каталогах и, разумеется, рекурсивно. Найдём в исходниках код, где разрешается использование Intel'ом сторонних SFP-шек. Как пишется allow_unsupported_sfp или unsupported_allow_sfp не помню. Ну да и ладно — это проблемы grep'а:
root@nm3:/ # grep -rni allow /usr/src/sys/dev/ | grep unsupp
/usr/src/sys/dev/ixgbe/README:75:of unsupported modules by setting the static variable 'allow_unsupported_sfp'
/usr/src/sys/dev/ixgbe/ixgbe.c:322:static int allow_unsupported_sfp = TRUE;
/usr/src/sys/dev/ixgbe/ixgbe.c:323:TUNABLE_INT("hw.ixgbe.unsupported_sfp", &allow_unsupported_sfp);
/usr/src/sys/dev/ixgbe/ixgbe.c:542: hw->allow_unsupported_sfp = allow_unsupported_sfp;
/usr/src/sys/dev/ixgbe/ixgbe_type.h:3249: bool allow_unsupported_sfp;
/usr/src/sys/dev/ixgbe/ixgbe_phy.c:1228: if (hw->allow_unsupported_sfp == TRUE) {
Надеюсь не утомил. И это была только вершина айсберга grep. Приятного Вам чтения, а мне аппетита на шашлыках!
Ну и удачного Вам grep'a!