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

178

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

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

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

Теги:
string
grep

10 ответов

357
Лучший ответ
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 в свой код выхода, это означает, что условие истинно; в противном случае - false.

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

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

  • 0
    Больше информации о grep и доступных опциях в asnwer stackoverflow.com/a/4749368/1702557
  • 1
    Возможно, вы захотите рассмотреть параметры -Fxq как в stackoverflow.com/a/4749368/544721
Показать ещё 3 комментария
26

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

В 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".

8
##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 available"
else
echo "Oops!!Not available"
fi
  • 1
    Изменение каталога обычно не является хорошей идеей (и здесь совершенно не нужно, просто укажите имя файла с целевым каталогом). И то, что у вас есть, - это то же самое, что принятый ответ, только с меньшим количеством деталей.
  • 0
    Спасибо за совет мат
5
grep -q [PATTERN] [FILE] && echo $?

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

2
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
1

Самая короткая (правильная) версия:

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"
  • 2
    if grep -q something file; then echo yes; else echo no; fi . Нет причин связываться с $? совсем.
0

Попробуйте следующее:

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

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

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.)
0

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

if grep $SearchTerm $FileToSearch; then
   echo "$SearchTerm found OK"
else
   echo "$SearchTerm not found"
fi
-4
grep -q "something" file
[[ !? -eq 0 ]] && echo "yes" || echo "no"
  • 1
    У вас есть опечатка -!? должен быть $?
  • 0
    ... не только он должен быть $? , но в этом нет необходимости - вы можете просто сделать это, if grep -q ...
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню