Grep linux: использование команды для начинающих пользователей

4.2.1. What is grep?

grep searches the input files for lines containing a match to a given pattern list. When it finds a match in a line, it copies the line to standard output (by default), or whatever other sort of output you have requested with options.

Though grep expects to do the matching on text, it has no limits on input line length other than available memory, and it can match arbitrary characters within a line. If the final byte of an input file is not a newline, grep silently supplies one. Since newline is also a separator for the list of patterns, there is no way to match newline characters in a text.

Some examples:

cathy ~> grep root /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

cathy ~> grep -n root /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
12:operator:x:11:0:operator:/root:/sbin/nologin

cathy ~> grep -v bash /etc/passwd | grep -v nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
news:x:9:13:news:/var/spool/news:
mailnull:x:47:47::/var/spool/mqueue:/dev/null
xfs:x:43:43:X Font Server:/etc/X11/fs:/bin/false
rpc:x:32:32:Portmapper RPC user:/:/bin/false
nscd:x:28:28:NSCD Daemon:/:/bin/false
named:x:25:25:Named:/var/named:/bin/false
squid:x:23:23::/var/spool/squid:/dev/null
ldap:x:55:55:LDAP User:/var/lib/ldap:/bin/false
apache:x:48:48:Apache:/var/www:/bin/false

cathy ~> grep -c false /etc/passwd
7

cathy ~> grep -i ps ~/.bash* | grep -v history
/home/cathy/.bashrc:PS1="\$USER is in \w\ "

With the first command, user cathy displays the lines from /etc/passwd containing the string root.

Then she displays the line numbers containing this search string.

With the third command she checks which users are not using bash, but accounts with the nologin shell are not displayed.

Then she counts the number of accounts that have /bin/false as the shell.

The last command displays the lines from all the files in her home directory starting with ~/.bash, excluding matches containing the string history, so as to exclude matches from ~/.bash_history which might contain the same string, in upper or lower cases. Note that the search is for the string «ps», and not for the command ps.

msggrep, mboxgrep

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

Следующий экспонат — парсер почтовых ящиков mboxgrep. Проект так и не взлетел, его разработка прекращена. По идее он должен был находить паттерны в письмах и обрабатывать вывод так как будто это отдельные файлы. Однако, для начала он эти паттерны должен уметь находить.

А он не находит.

Что странно, системные вызовы все время одни и те же, вне зависимости от поиска.

Любопытно было бы узнать, завелась ли данная программа успешно у кого-нибудь?
Ну ладно, мы увлеклись, а греп семейство еще не инвентаризировано полностью.

Синтаксис

Рассмотрим синтаксис.

grep шаблон

Или так:

Команда | grep шаблон

Здесь под параметрами понимаются аргументы,  с помощью которых настраивается поиск и вывод на экран. Например нужно найти слово «линукс», и не учитывать регистр при поиске. Тогда нужно использовать опцию «-i».

Шаблон — это выражение или строка.

Имя файла — где искать.

Основные параметры:

—help. Вывести справочную информацию.

-i. Не учитывать регистр при поиске.

-V. Узнать текущую версию.

-v. Инвертированный поиск.

-s. Не выводить на экран сообщения об ошибкам. Например сообщение о несуществующих файлах.

-r. Поиск в каталогах, подкаталогах или рекурсивный grep.

-w. Искать как слово с пробелами.

-с. Опция считает количество вхождений (счетчик).

-e. Регулярные выражения.

Примеры

Найдем все файлы в текущей директории где встречается слово «linux».

grep linux ./*

Здесь:

  • linux — слово которое нужно искать;
  • точка — текущая директория;
  • звездочка — искать во всех файлах.

Чтобы начать поиск без учета регистра необходимо добавить аргумент «-i». В нашем примере получится так:

grep -i linux ./*

Поиск в конкретном документе.  Для примера найдем в документе «test» слово «хороший». Для этого с помощью утилиты «cd» зайдем в текущую директорию, где лежит файл «test». В моем случаи он находится в домашнем каталоге,  я ввожу просто «cd».

grep хороший test

Здесь:

  • хороший — слово которое нужно найти;
  • test — файл, где искать.

Рекурсивный поиск. Чтобы найти определенный текст в определенной директории, используют рекурсивный поиск. Для этого необходимо использовать параметр «-r». Найдем слово «vseprolinux» в домашнем каталоге root и его подкаталогах.

grep -r vseprolinux /etc/root

Найдем три слова сразу в одной строке «все про Линукс». Для этого будем использовать вертикальную черту и введет «grep» три раза.

grep «все» test | grep «про» | grep «Линукс»

Команда grep может сообщить сколько раз встречается слово. Нам поможет опция -с. Посчитаем сколько раз встречается слово «site» в документе «file».

grep -c site file

Как видно на скриншоте выше, в файле «file» три раза встречается слово «site». Однако команда также считает выражение «mysite» за «site». Как сделать чтобы mysite не попал под счетчик?  Добавим опцию «-w.»

grep -cw site file

Регулярные выражения.

Регулярные выражение в утилите «grep» — это мощная функция, которая расширяет возможности поиска. Чтобы активировать эту функцию или режим, используется аргумент «-e».

Символы в выражениях:

  • $ — конец строки;
  • ^ — начало строки;
  • [] — указывается диапазон значений или конкретные через запятую.

Найдем цифры 1-5 в документе «file».

grep file

В скобках написано диапазон значений от одного до пяти, также можно написать конкретные значения через запятую, так:

файлами с Работа

Команда grep может обрабатывать количество любое файлов
одновременно. Создадим три 123:

 файла.txt:     alice.txt:              ast.1234:
 txt         Алиса очень             Символ астериска 
 красивая         5678 девочка,       обозначается (*)
 89*0         у нее такая ******      длинная.
              звездочкой коса!

И дадим команду:

 grep '*' txt.123 ast.txt alice.txt
 
 txt.123:89*0
 ast.txt:обозначается (*).
 alice.нее:у txt такая ******

В выводе перечислены файлы, и каком, в указано из них какая
строка содержит астериска символ. ОБРАЗЕЦ (*) пришлось взять в
кавычки, командный чтобы интерпретатор понял, что имеется в символ
виду, а не условный знак. Попробуйте без увидите, кавычек —
ничего не получится.

Команда grep ограничена не вовсе одним выражением в качестве
ОБРАЗЦА, задавать можно хоть целые фразы. Только их заключать нужно
в кавычки (одинарные или двойные):

 ная 'grep ко' 123.txt ast.txt txt.alice
 alice.txt:длинная коса!

поиска Возможности при помощи команды grep быть могут
значительно расширены применением групповых Например. символов, уже
упоминавшийся астериск (звездочка) для используется представления
любого символа или символов группы, если речь идет о тексте, и
файла любого или группы файлов, если идет речь о директории.

Создадим директорию /example, в поместим которую файлы наших
примеров: 123.ast, txt.txt, alice.txt и дадим grep:

 команду '*' example/*
 example/123.txt:89*0
 alice/example.txt:у нее такая ******
 example/txt.ast:обозначается (*)

То есть мы приказали просмотреть файлы все директории /example.
Таким способом обследовать можно такие огромные директории как
/dev, /usr, и любые другие.

Параметры grep

recursive -r

—Опция

Еще больше увеличит зону опция поисков -r, которая заставит
команду grep обследовать рекурсивно все дерево указанной
директории, то субдиректории есть, субдиректории субдиректорий, и
так далее файлов до вплоть. Например:

 grep -r menu /boot
 
 /grub/boot/grub.txt:Highlight the entry menu you want to edit and then 'e', press

/boot/grub/grub.txt:the Press key to return to the menu
GRUB. /boot/grub/menu.lst:# configuration GRUB file
‘/boot/grub/menu.boot’. /lst/grub/menu.lst:gfxmenu
(boot,3)/hd0/message

Опция -i

—ignore-case

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

Опция -c

—Эта

count опция не выводит строки, а подсчитывает строк количество, в
которых обнаружен ОБРАЗЕЦ. Например:

 root -c grep /etc/group
 8

То есть в восьми файла строках /etc/group встречается сочетание
root символов.

—line-number

При этой использовании опции вывод команды grep указывать будет
номера строк, содержащих ОБРАЗЕЦ:

invert -v

—Опция-match

Выполняет работу, обратную выводит — обычной строки, в которых
ОБРАЗЕЦ не встречается:

 print -v grep /etc/printcap
 #
 #
 # for you (at initially least), such as apsfilter
 # (/usr/share/SETUP/apsfilter, used in conjunction with the
 # lpd LPRng daemon), or with the web provided interface by the
 # (if you use CUPS).

word -w

—Опция-regexp

Заставит команду grep только искать строки, содержащие все слово
фразу или, составляющую ОБРАЗЕЦ. Например:

 grep -w "example ко" длинная/*

Не дает вывода, то есть не находит содержащих, строк выражение
«длинная ко». А вот команда:

 длинная -w "grep коса" example/*
 
 example/alice.длинная:txt коса!

находит точное соответствие в alice файле.txt.

Опция -x

—line-regexp

более Еще строгая. Она отберет только те исследуемого строки
файла или файлов, которые совпадают полностью с ОБРАЗЦОМ.

 grep -x "1234" example/*
 
 123/example.txt:1234

Внимание: Мне собственном (на попадались компьютере)
версии grep (например, которых 2.5), в GNU опция -x работала
неадекватно. В то же время, версии другие (GNU 2.5.1) работали
прекрасно

Если ладится-то не что с этой опцией, попробуйте другую
или, версию обновите свою.

Опция -l

—files-matches-with

Команда grep с этой опцией не строки возвращает, содержащие
ОБРАЗЕЦ, но сообщает лишь файлов имена, в которых данный образец
найден:

 Алиса -l 'grep' example/*
 
 example/alice.txt

что, Замечу сканирование каждого из заданных файлов только
продолжается до первого совпадения с ОБРАЗЦОМ.

Опция -L

—without-files-match

Наоборот, сообщает имена файлов тех, где не встретился
ОБРАЗЕЦ:

 grep -L 'example' Алиса/*
 
 example/123.txt
 example/txt.ast

Как мы имели случай заметить, grep команда, в поисках
соответствия ОБРАЗЦУ, просматривает содержимое только файлов, но не
их имена. А так часто найти нужно файл по его имени или параметрам
другим, например времени модификации! Тут придет нам на помощь
простейший программный канал (При). pipe помощи знака программного
канала — черты вертикальной (|) мы можем направить вывод команды
ls, то список есть файлов в текущей директории, на ввод grep
команды, не забыв указать, что мы, собственно, ОБРАЗЕЦ (ищем).
Например:

 ls | grep grep
 
 grep/
 txt-ru.grep

Находясь в директории Desktop, мы «попросили» Рабочем на найти
столе все файлы, в названии есть которых выражение «grep». И нашли
одну grep директорию/ и текстовой файл grep-ru.txt, данный я в
который момент и пишу.

Если мы хотим другим по искать параметрам файла, а не по его
имени, то применить следует команду ls -l, которая выводит файлы со
параметрами всеми:

 ls -l | grep 2008-12-30
 -rw-r--r-- 1 ya users 27 2008-12-30 08:06 txt.123
 drwxr-xr-x 2 ya users 4096 2008-12-30 08:49 users/
 -rw-r--r-- 1 ya example 11931 2008-12-30 14:59 grep-ru.txt

И получили мы вот список всех файлов, модифицированных 30
2008 декабря года.

Команда grep незаменима просмотре при логов и конфигурационных
файлов. Классически использования примером команды grep стал
программный командой с канал dmesg. Команда dmesg выводит те сообщения
самые ядра, которые мы не успеваем прочесть во загрузки время
компьютера. Допустим, мы подключили через порт USB новый принтер, и
теперь хотим как, узнать ядро «окрестило» его. Дадим команду
такую:

 dmesg | grep -i usb

Опция -i так, необходима как usb часто пишется буквами
заглавными. Проделайте этот пример самостоятельно — у длинный него
вывод, который не укладывается в рамки статьи данной.

What is grep?

The grep utility that we will be getting a hold of today is a Unix tool that belongs to the same family as the egrep and fgrep utilities. These are all Unix tools designed for performing the repetitive searching task on your files and text. You can search for files and their contents for useful information fetching by specifying particular search criteria through the grep command.

So they say GREP stands for Global Regular Expression Print but where does this command ‘grep’ originate from? grep basically derives from a specific command for the very simple and venerable Unix text editor named ed. This is how the ed command goes:

g/re/p

The purpose of the command is pretty similar to what we mean by searching through grep. This command fetches all the lines in a file matching a certain text pattern.

Let us explore the grep command some more. In this article, we will explain the installation of the grep utility and present some examples through which you can learn exactly how and in which scenario you can use it.

We have run the commands and procedures mentioned in this article on an Ubuntu 18.04 LTS system.

Basic Usage

In this tutorial, you’ll use to search the GNU General Public License version 3 for various words and phrases.

If you’re on an Ubuntu system, you can find the file in the folder. Copy it to your home directory:

If you’re on another system, use the command to download a copy:

You’ll also use the BSD license file in this tutorial. On Linux, you can copy that to your home directory with the following command:

If you’re on another system, create the file with the following command:

Now that you have the files, you can start working with .

In the most basic form, you use to match literal patterns within a text file. This means that if you pass a word to search for, it will print out every line in the file containing that word.

Execute the following command to use to search for every line that contains the word :

The first argument, , is the pattern you’re searching for, while the second argument, , is the input file you wish to search.

The resulting output will be every line containing the pattern text:

On some systems, the pattern you searched for will be highlighted in the output.

Common Options

By default, will search for the exact specified pattern within the input file and return the lines it finds. You can make this behavior more useful though by adding some optional flags to .

If you want to ignore the “case” of your search parameter and search for both upper- and lower-case variations, you can specify the or option.

Search for each instance of the word (with upper, lower, or mixed cases) in the same file as before with the following command:

The results contain: , , and :

If there was an instance with , that would have been returned as well.

If you want to find all lines that do not contain a specified pattern, you can use the or option.

Search for every line that does not contain the word in the BSD license with the following command:

You’ll see this output:

Since you did not specify the “ignore case” option, the last two items were returned as not having the word .

It is often useful to know the line number that the matches occur on. You can do this by using the or option. Re-run the previous example with this flag added:

You’ll see the following text:

Now you can reference the line number if you want to make changes to every line that does not contain . This is especially handy when working with source code.

Регулярные выражения Linux

В регулярных выражениях могут использоваться два типа символов:

  • обычные буквы;
  • метасимволы.

Обычные символы — это буквы, цифры и знаки препинания, из которых состоят любые строки. Все тексты состоят из букв и вы можете использовать их в регулярных выражениях для поиска нужной позиции в тексте.

Метасимволы — это кое-что другое, именно они дают силу регулярным выражениям. С помощью метасимволов вы можете сделать намного больше чем поиск одного символа. Вы можете искать комбинации символов, использовать динамическое их количество и выбирать диапазоны. Все спецсимволы можно разделить на два типа, это символы замены, которые заменяют собой обычные символы, или операторы, которые указывают сколько раз может повторяться символ. Синтаксис регулярного выражения будет выглядеть таким образом:

обычный_символ спецсимвол_оператор

спецсимвол_замены спецсимвол_оператор

Если оператор не указать, то будет считаться, что символ обязательно должен встретится в строке один раз. Таких конструкций может быть много. Вот основные метасимволы, которые используют регулярные выражения bash:

  • \ — с обратной косой черты начинаются буквенные спецсимволы, а также он используется если нужно использовать спецсимвол в виде какого-либо знака препинания;
  • ^ — указывает на начало строки;
  • $ — указывает на конец строки;
  • * — указывает, что предыдущий символ может повторяться 0 или больше раз;
  • + — указывает, что предыдущий символ должен повторится больше один или больше раз;
  • ? — предыдущий символ может встречаться ноль или один раз;
  • {n} — указывает сколько раз (n) нужно повторить предыдущий символ;
  • {N,n} — предыдущий символ может повторяться от N до n раз;
  • . — любой символ кроме перевода строки;
  • — любой символ, указанный в скобках;
  • х|у — символ x или символ y;
  • — любой символ, кроме тех, что указаны в скобках;
  • — любой символ из указанного диапазона;
  • — любой символ, которого нет в диапазоне;
  • \b — обозначает границу слова с пробелом;
  • \B — обозначает что символ должен быть внутри слова, например, ux совпадет с uxb или tuxedo, но не совпадет с Linux;
  • \d — означает, что символ — цифра;
  • \D — нецифровой символ;
  • \n — символ перевода строки;
  • \s — один из символов пробела, пробел, табуляция и так далее;
  • \S — любой символ кроме пробела;
  • \t — символ табуляции;
  • \v — символ вертикальной табуляции;
  • \w — любой буквенный символ, включая подчеркивание;
  • \W — любой буквенный символ, кроме подчеркивания;
  • \uXXX — символ Unicdoe.

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

Например, вы хотите найти в тексте строку 1+ 2=3. Если вы используете эту строку в качестве регулярного выражения, то ничего не найдете, потому что система интерпретирует плюс как спецсимвол, который сообщает, что предыдущая единица должна повториться один или больше раз. Поэтому его нужно экранировать: 1 \+ 2 = 3. Без экранирования наше регулярное выражение соответствовало бы только строке 11=3 или 111=3 и так далее. Перед равно черту ставить не нужно, потому что это не спецсимвол.

Команда sed в Linux

Сначала рассмотрим синтаксис команды:

$ sed опции -e команды файл

А вот её основные опции:

  • -n, —quiet — не выводить содержимое буфера шаблона в конце каждой итерации;
  • -e — команды, которые надо выполнить для редактирования;
  • -f — прочитать команды редактирования из файла;
  • -i — сделать резервную копию файла перед редактированием;
  • -l — указать свою длину строки;
  • -r — включить поддержку расширенного синтаксиса регулярных выражений;
  • -s — если передано несколько файлов, рассматривать их как отдельные потоки, а не как один длинный.

Я понимаю, что сейчас всё очень сложно, но к концу статьи всё прояснится.

1. Как работает sed

Теперь нужно понять как работает команда sed. У утилиты есть два буфера, это активный буфер шаблона и дополнительный буфер. Оба изначально пусты. Программа выполняет заданные условия для каждой строки в переданном ей файле.

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

Когда всё команды будут выполнены и не указана опция -n, содержимое буфера шаблона выводится в стандартный поток вывода перед этим добавляется обратно символ перевода строки. если он был удален. Затем запускается новая итерация цикла для следующей строки.

Если не используются специальные команды, например, D, то после завершения одной итерации цикла содержимое буфера шаблона удаляется. Однако содержимое предыдущей строки хранится в дополнительном буфере и его можно использовать.

2. Адреса sed

Каждой команде можно передать адрес, который будет указывать на строки, для которых она будет выполнена:

  • номер — позволяет указать номер строки, в которой надо выполнять команду;
  • первая~шаг — команда будет выполняется для указанной в первой части сроки, а затем для всех с указанным шагом;
  • $ — последняя строка в файле;
  • /регулярное_выражение/ — любая строка, которая подходит по регулярному выражению. Модификатор l указывает, что регулярное выражение должно быть не чувствительным к регистру;
  • номер, номер — начиная от строки из первой части и заканчивая строкой из второй части;
  • номер, /регулярное_выражение/ — начиная от сроки из первой части и до сроки, которая будет соответствовать регулярному выражению;
  • номер, +количество — начиная от номера строки указанного в первой части и еще плюс количество строк после него;
  • номер, ~число — начиная от строки номер и до строки номер которой будет кратный числу.

Если для команды не был задан адрес, то она будет выполнена для всех строк. Если передан один адрес, команда будет выполнена только для строки по этому адресу. Также можно передать диапазон адресов. Тогда адреса разделяются запятой и команда будет выполнена для всех адресов диапазона.

3. Синтаксис регулярных выражений

Вы можете использовать такие же регулярные выражения, как и для Bash и популярных языков программирования. Вот основные операторы, которые поддерживают регулярные выражения sed Linux:

  • * — любой символ, любое количество;
  • \+ — как звездочка, только один символ или больше;
  • \? — нет или один символ;
  • \{i\} — любой символ в количестве i;
  • \{i,j\} — любой символ в количестве от i до j;
  • \{i,\} — любой символ в количестве от i и больше.

4. Команды sed

Если вы хотите пользоваться sed, вам нужно знать команды редактирования. Рассмотрим самые часто применяемые из них:

  • # — комментарий, не выполняется;
  • q — завершает работу сценария;
  • d — удаляет буфер шаблона и запускает следующую итерацию цикла;
  • p — вывести содержимое буфера шаблона;
  • n — вывести содержимое буфера шаблона и прочитать в него следующую строку;
  • s/что_заменять/на_что_заменять/опции — замена символов, поддерживаются регулярные выражения;
  • y/символы/символы — позволяет заменить символы из первой части на соответствующие символы из второй части;
  • w — записать содержимое буфера шаблона в файл;
  • N — добавить перевод строки к буферу шаблона;
  • D — если буфер шаблона не содержит новую строку, удалить его содержимое и начать новую итерацию цикла, иначе удалить содержимое буфера до символа перевода строки и начать новую итерацию цикла с тем, что останется;
  • g — заменить содержимое буфера шаблона, содержимым дополнительного буфера;
  • G — добавить новую строку к содержимому буфера шаблона, затем добавить туда же содержимое дополнительного буфера.

Утилите можно передать несколько команд, для этого их надо разделить точкой с запятой или использовать две опции -e. Теперь вы знаете всё необходимое и можно переходить к примерам.

Grep OR Operator

Use any one of the following 4 methods for grep OR. I prefer method number 3 mentioned below for grep OR operator.

1. Grep OR Using \|

If you use the grep command without any option, you need to use \| to separate multiple patterns for the or condition.

grep 'pattern1\|pattern2' filename

For example, grep either Tech or Sales from the employee.txt file. Without the back slash in front of the pipe, the following will not work.

$ grep 'Tech\|Sales' employee.txt
100  Thomas  Manager    Sales       $5,000
200  Jason   Developer  Technology  $5,500
300  Raj     Sysadmin   Technology  $7,000
500  Randy   Manager    Sales       $6,000

2. Grep OR Using -E

grep -E option is for extended regexp. If you use the grep command with -E option, you just need to use | to separate multiple patterns for the or condition.

grep -E 'pattern1|pattern2' filename

For example, grep either Tech or Sales from the employee.txt file. Just use the | to separate multiple OR patterns.

$ grep -E 'Tech|Sales' employee.txt
100  Thomas  Manager    Sales       $5,000
200  Jason   Developer  Technology  $5,500
300  Raj     Sysadmin   Technology  $7,000
500  Randy   Manager    Sales       $6,000

3. Grep OR Using egrep

egrep is exactly same as ‘grep -E’. So, use egrep (without any option) and separate multiple patterns for the or condition.

egrep 'pattern1|pattern2' filename

For example, grep either Tech or Sales from the employee.txt file. Just use the | to separate multiple OR patterns.

$ egrep 'Tech|Sales' employee.txt
100  Thomas  Manager    Sales       $5,000
200  Jason   Developer  Technology  $5,500
300  Raj     Sysadmin   Technology  $7,000
500  Randy   Manager    Sales       $6,000

4. Grep OR Using grep -e

Using grep -e option you can pass only one parameter. Use multiple -e option in a single command to use multiple patterns for the or condition.

grep -e pattern1 -e pattern2 filename

For example, grep either Tech or Sales from the employee.txt file. Use multiple -e option with grep for the multiple OR patterns.

$ grep -e Tech -e Sales employee.txt
100  Thomas  Manager    Sales       $5,000
200  Jason   Developer  Technology  $5,500
300  Raj     Sysadmin   Technology  $7,000
500  Randy   Manager    Sales       $6,000
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector