Так, здесь у нас есть две команды:
cat /var/log/dpkg.log | grep " \install\ "
cat /var/log/dpkg.log | grep install
Почему отличаются выводы этих команд? И можно ли объяснить первую команду немного.Заранее спасибо.
Первая часть Ваших двух команд (cat FILENAME
) всегда то же и просто печатает содержание указанного файла к потоку STDOUT. Я не объясню это дальше.
Точка нашего интереса grep
часть.
grep
:grep [OPTIONS] PATTERN [FILE...]
Можно передать grep
некоторые опции настроить его поведение (например, установить используемый аромат RegEx или управлять выходным форматированием), но они не используются в Вашем случае.
Следующий отдельный аргумент должен быть шаблоном для соответствия, где регулярное выражение ("RegEx") или фиксированная строка (если grep
назван с -F
опция), требуется. В Вашем примере это install
или "\ install\ "
часть. Я объясню это в следующем абзаце.
После этого Вы указываете источник данных для соответствия. Это может или быть именем файла или ничем. Во втором случае, grep
будет читать из потока STDIN (стандартный вход: обычно, что Вы вводите с клавиатурой), где Вы передаете по каналу (|
) вывод от предыдущей команды.
Параметр шаблона должен быть отдельным аргументом. Это означает, Вы не можете только передать несколько слов или что-либо содержащее пробелы или окружить специальные символы здесь, потому что пробелы рассматривают как разделители аргумента в Bash и вероятно любой оболочке также, и окружают специальные символы такой как ;
повредит команду.
Но у Вас есть две опции включать пробелы в шаблон для соответствия так или иначе:
Поместите всю строку для соответствия в единственном ('...'
) или дважды ("..."
) кавычки. Таким образом, оболочка анализирует всю включенную в кавычки строку как один аргумент и передает его на grep
.
Выйдите из каждого пространства в шаблоне с обратной косой чертой (\
). Это означает, Вы пишете обратную косую черту перед каждым пространством, которое Вы не хотите рассматриваться как разделитель аргумента оболочкой. Но обратите внимание, что, если Вы хотите иметь фактическую обратную косую черту в шаблоне, необходимо выйти из него также путем записи другой обратной косой черты перед ним.
Если мы теперь анализируем различие Ваших двух grep
примеры команды, мы видим различие в том, чему они соответствуют:
cat /var/log/dpkg.log | grep "\ install\ "
Это соответствует шаблону install
. (Отметьте продвижение и конечный пробел!)
Здесь мы видим оба метода: двойные кавычки вокруг всего шаблона и выхода обратной косой черты пробелы в нем. Это является лишним честно говоря, можно было бы быть достаточно. Хотя это не причиняет боль в этом случае, Вы не должны делать этого и выбирать один метод. Обычно я рекомендовал бы использовать кавычки, поскольку легче читать.
cat /var/log/dpkg.log | grep install
Это соответствует шаблону install
. (Никакие окружающие пробелы.)
Здесь шаблон только состоит из слова install
, ничто иное. Никакие пробелы.
Как я сказал, первый из Ваших примеров только распознает слово install
когда это окружается пробелами. Это не соответствовало бы, если, например, существует точка или какой-либо другой символ непосредственно прежде или после него вместо этого. Это также не распознало бы слово непосредственно вначале или конец строки.
Второй пример не заботится ни о каких пробелах прежде или после слова install
. Это также соответствует в начале строки и окончаниях, а также если это окружается пунктуацией. Это даже соответствует, если существует слово, содержащее эту последовательность буквы где-нибудь, например, "удаление", "переустановите" или "установка" также!
Как в примере Вы, если обратные косые черты являются лишними, здесь тот же пример без кавычек, но с обратной косой чертой, выходящей только вместо этого:
cat /var/log/dpkg.log | grep \ install\
Или если Вы хотите соответствовать строке, "Мне нравится Ubuntu" в файле /home/you/path with spaces/textfile
не используя кавычки, Вы сделали бы это как это:
grep I\ like\ Ubuntu /home/you/path\ with\ spaces/textfile
Вы видите, что необходимо выйти из пробелов в пути - или имена файлов также - или заключить им в кавычки. Строка выше равна строке ниже:
grep "I like Ubuntu" "/home/you/path with spaces/textfile"
Вторая (более простая) форма будет соответствовать заданной строке в любом месте строки: например, она будет соответствовать строкам, подобным install ation, re install , install и т. Д.
Первое выражение будет соответствовать install только там, где на каждом конце есть пробел. Обратная косая черта - это что-то вроде красной сельди, так как кавычек уже достаточно (и первая - без надобности - экранирует i
, а не пробел): однако она могла бы быть написана с использованием , только экранированных слов обратной
cat /var/log/dpkg.log | grep \ install\
(NB, в конце вышеуказанной команды есть буквальный пробел).
Добавление одного пробела в шаблон - это немного хак, ИМХО: он не будет работать, если шаблон отделен другим пробелом (табуляцией или окончанием строки). Лучшим вариантом может быть использование явных границ слов, например
grep '\binstall\b' /var/log/dpkg.log
или используйте переключатель -w
(--word-regexp
)
grep -w 'install' /var/log/dpkg.log
(хотя они включают дефисы и пробелы - так что эквивалентность не точна). Если вы действительно хотите получить экземпляры шаблона, разделенные пробелами, то вы можете использовать класс символов [[:space:]]
POSIX, например
grep '[[:space:]]install[[:space:]]' /var/log/dpkg.log
Первая команда:
cat /var/log/dpkg.log | grep " \install\ "
Как указывало @ByteCommander, возможна опечатка, и команда должна быть
cat /var/log/dpkg.log | grep "\ install\ "
Это будет соответствовать строке install
с конечным и начальным пробелом. Этого также можно достичь с помощью grep -w "install"
. Кроме того, \
не требуется, когда вы используете кавычки.
Вторая команда:
cat /var/log/dpkg.log | grep install
Эта команда также соответствует строкам, содержащим install
. Например, « установить ред».
Тестовый пример:
содержимое тестового файла:
foo
bar
foobar
foo bar
Выполнение:
cat file1.txt | grep foo
foo
foobar
foo bar
cat file1.txt | grep -w foo
foo
foo bar
cat file1.txt | grep "foo "
foo bar