Как проверить, содержит ли файл определенную строку, используя Bash

266

Я хочу проверить, содержит ли файл определенную строку или нет в bash. Я использовал этот скрипт, но он не работает:

 if [[ 'grep 'SomeString' $File' ]];then
   # Some Actions
 fi

Что не так в моем коде?

крупный чиновник
источник
2
Аналогично stackoverflow.com/questions/4749330/…
Pawel
Вот как Grep выходных данных command: stackoverflow.com/questions/12375722/...
rogerdpack

Ответы:

466
if grep -q SomeString "$File"; then
  Some Actions # SomeString was found
fi

Вам не нужно [[ ]]здесь. Просто запустите команду напрямую. Добавить -qопцию, когда вам не нужна строка, отображаемая, когда она была найдена.

Команда grepвозвращает 0 или 1 в коде выхода в зависимости от результата поиска. 0 если что-то было найдено; 1 иначе.

$ echo hello | grep hi ; echo $?
1
$ echo hello | grep he ; echo $?
hello
0
$ echo hello | grep -q he ; echo $?
0

Вы можете указать команды как условие if. Если команда возвращает 0 в своем коде выхода, это означает, что условие истинно; иначе ложно.

$ if /bin/true; then echo that is true; fi
that is true
$ if /bin/false; then echo that is true; fi
$

Как видите, вы запускаете здесь программы напрямую. Никаких дополнительных []или [[]].

Игорь Чубин
источник
Более подробная информация grepи доступные опции в asnwer stackoverflow.com/a/4749368/1702557
Pawel
2
Возможно, вы захотите рассмотреть -Fxqпараметры, как в stackoverflow.com/a/4749368/544721
Гжегож Вежовецкий,
3
рассмотрите возможность использования -m 1для улучшения производительности сканирования. Возвращает при первом появлении.
Алик Эльзин-килака
1
если SomeStringсодержит специальные символы регулярного выражения (например .), вы можете получить неожиданные результаты. Всегда безопаснее использовать fgrep(или grep -F) (если только вам действительно не нужно регулярное выражение, в этом случае egrep(или grep -E), вероятно, лучший выбор)
Уолтер Тросс
Пример ifпримера неверен, так как он только проверяет, был ли код выхода не равен 0. Если происходит какая-либо ошибка, например, если файл не может быть прочитан, код выхода также не равен 0. Таким образом, вы должны сделать что-то подобное ec=$?, и проверить, если это 0(найдено), затем, если оно 1(не найдено), и затем, если это что-то еще (сбой).
ддеканы
40

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

В Bash ifследует команда. Если код выхода этой команды равен 0, то thenчасть выполняется, иначе выполняется elseчасть, если она есть.

Вы можете сделать это с помощью любой команды, как описано в других ответах: if /bin/true; then ...; fi

[[это внутренняя команда bash, предназначенная для некоторых тестов, таких как существование файла, сравнение переменных. Аналогичным образом [, это внешняя команда (обычно она находится в /usr/bin/[), которая выполняет примерно те же тесты, но нуждается ]в качестве окончательного аргумента, поэтому ее ]необходимо дополнить пробелом слева, а это не так ]].

Здесь вам не нужно [[ни [.

Другое дело, как вы цитируете вещи. В bash есть только один случай, когда пары кавычек вкладывают, это так "$(command "argument")". Но у 'grep 'SomeString' $File'вас есть только одно слово, потому что 'grep 'это единица в кавычках, которая соединяется с, SomeStringа затем снова соединяется с ' $File'. Переменная $Fileдаже не заменяется своим значением из-за использования одинарных кавычек. Правильный способ сделать это grep 'SomeString' "$File".

Benoit
источник
15

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

if ! grep -q SomeString "$File"; then
  Some Actions # SomeString was not found
fi
Лахиру Чандима
источник
10
##To check for a particular  string in a file

cd PATH_TO_YOUR_DIRECTORY #Changing directory to your working directory
File=YOUR_FILENAME  
if grep -q STRING_YOU_ARE_CHECKING_FOR "$File"; ##note the space after the string you are searching for
then
echo "Hooray!!It's available"
else
echo "Oops!!Not available"
fi
Невин Радж Виктор
источник
2
Изменение каталога, как правило, не очень хорошая идея (и здесь совершенно не нужно, просто укажите имя файла с целевым каталогом). И то, что у вас есть, - это то же самое, что принятый ответ, только с меньшим количеством деталей.
Мат
Спасибо за совет Мат
Невин Радж Виктор
7

Кратчайшая (правильная) версия:

grep -q "something" file; [ $? -eq 0 ] && echo "yes" || echo "no"

можно также записать как

grep -q "something" file; test $? -eq 0 && echo "yes" || echo "no"

но вам не нужно явно проверять это в этом случае, так же как с:

grep -q "something" file && echo "yes" || echo "no"
lzap
источник
3
if grep -q something file; then echo yes; else echo no; fi, Нет причин связываться $?вообще.
Чарльз Даффи
6

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

grep -Fxq [String] [filePath]

пример

 searchString="Hello World"
 file="./test.log"
 if grep -Fxq "$searchString" $file
    then
            echo "String found in $file"
    else
            echo "String not found in $file"
 fi

Из файла man:

-F, --fixed-strings

          Interpret  PATTERN  as  a  list of fixed strings, separated by newlines, any of 

which is to be matched.
          (-F is specified by POSIX.)
-x, --line-regexp
          Select only those matches that exactly match the whole line.  (-x is specified by 

POSIX.)
-q, --quiet, --silent
          Quiet; do not write anything to standard output.  Exit immediately with zero 

status  if  any  match  is
          found,  even  if  an error was detected.  Also see the -s or --no-messages 

option.  (-q is specified by
          POSIX.)
Шубхам Хатри
источник
6
grep -q [PATTERN] [FILE] && echo $?

Статус выхода 0(true), если шаблон был найден; в противном случае пустая строка.

SupermanKelly
источник
4
if grep -q [string] [filename]
then
    [whatever action]
fi

пример

if grep -q 'my cat is in a tree' /tmp/cat.txt
then
    mkdir cat
fi
user5854766
источник
2

Попробуй это:

if [[ $(grep "SomeString" $File) ]] ; then
   echo "Found"
else
   echo "Not Found"
fi
vgokul129
источник
3
Я нерешительно воздерживаюсь от этого, но переполнение стека не должно увековечивать подобную логику кренделя. grepвозвращает статус выхода по очень веской причине; Захват вывода в строку потенциально может сохранить большой объем текста в буфере, чтобы вы могли сказать, что он не пустой.
tripleee
-1

Я сделал это, кажется, работает нормально

if grep $SearchTerm $FileToSearch; then
   echo "$SearchTerm found OK"
else
   echo "$SearchTerm not found"
fi
madarekrap
источник
Цитата не работает , и вы, вероятно, хотите, чтобы не видеть вывод из grep.
трипл
-3
grep -q "something" file
[[ !? -eq 0 ]] && echo "yes" || echo "no"
chemila
источник
1
У вас есть опечатка -!? должен быть $?
2012 года
... не только так и должно быть $?, но в этом вообще нет необходимости - вы могли бы просто сделать этоif grep -q ...
Чарльз Даффи
1
Более того, foo && truthy_action || falsey_actionэто не настоящий троичный оператор - если truthy_actionне получится, то falsey_actionзапустится дополнительно .
Чарльз Даффи
В целом, цель в ifэто запустить команду и проверить ее код выхода. Вы должны очень редко должны исследовать $?явно.
tripleee