Как проверить, существует ли строка в файле с Bash?

У меня есть файл, содержащий имена каталогов:

my_list.txt:

/tmp
/var/tmp

Я хочу проверить Bash, прежде чем добавить имя каталога, если это имя уже существует в файле.

Ответ 1

grep -Fxq "$FILENAME" my_list.txt

Статус выхода равен 0 (true), если имя найдено, 1 (false), если нет, поэтому:

if grep -Fxq "$FILENAME" my_list.txt
then
    # code if found
else
    # code if not found
fi

Объяснение

Вот соответствующие разделы страницы руководства для grep:

grep [options] PATTERN [FILE...]

-F, --fixed-strings

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

-x, --line-regexp

Выберите только те совпадения, которые точно соответствуют всей строке.

-q, --quiet, --silent

Тихо; не пишите ничего в стандартный вывод. Выйдите немедленно с нулевым статусом, если найдено какое-либо совпадение, даже если обнаружена ошибка. Также см. параметр -s или --no-messages.

Обработка ошибок

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

Обычно статус выхода равен 0, если найдены выбранные строки, и 1 в противном случае. Но состояние выхода равно 2, если произошла ошибка, если только не используется опция -q или --quiet или --silent и не найдена выбранная строка. Однако обратите внимание, что POSIX только для программ, таких как grep, cmp и diff, обязывает, чтобы состояние выхода в случае ошибки было больше 1; поэтому для переносимости целесообразно использовать логику, которая проверяет это общее условие, вместо строгого равенства с 2.

Чтобы подавить нормальный выходной сигнал из grep, вы можете перенаправить его на /dev/null. Обратите внимание, что стандартная ошибка остается ненаправленной, поэтому любые сообщения об ошибках, которые может напечатать grep, будут появляться на консоли, как вы, вероятно, захотите.

Для обработки трех случаев мы можем использовать оператор case:

case 'grep -Fx "$FILENAME" "$LIST" >/dev/null; echo $?' in
  0)
    # code if found
    ;;
  1)
    # code if not found
    ;;
  *)
    # code if an error occurred
    ;;
esac

Ответ 2

Что касается следующего решения:

grep -Fxq "$FILENAME" my_list.txt

Если вам интересно (как и я), что означает -Fxq на простом английском языке:

  • F: влияет на интерпретацию PATTERN (фиксированная строка вместо регулярного выражения)
  • x: совпадение всей строки
  • q: Shhhhh... минимальная печать

Из файла 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.)

Ответ 3

Три метода в моем сознании:

1) Короткий тест для имени в пути (я не уверен, что это может быть ваш случай)

ls -a "path" | grep "name"


2) Короткий тест для строки в файле

grep -R "string" "filepath"


3) Дольше bash script с использованием регулярного выражения:

#!/bin/bash

declare file="content.txt"
declare regex="\s+string\s+"

declare file_content=$( cat "${file}" )
if [[ " $file_content " =~ $regex ]] # please note the space before and after the file content
    then
        echo "found"
    else
        echo "not found"
fi

exit

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

Ответ 4

Простейший способ:

if grep "$filename" my_list.txt > /dev/null
then
   ... found
else
   ... not found
fi

Совет: отправьте на /dev/null, если вы хотите получить статус выхода, но не выходы.

Ответ 5

Самый простой и простой способ:

isInFile=$(cat file.txt | grep -c "string")


if [ $isInFile -eq 0 ]; then
   #string not contained in file
else
   #string is in file at least once
fi

grep -c вернет счет того, сколько раз строка в файле появляется.

Ответ 6

Если я правильно понял ваш вопрос, это должно сделать то, что вам нужно.

  • вы можете указать каталог, который хотите добавить через переменную $check
  • Если каталог уже находится в списке, на выходе будет указан "dir, уже указанный"
  • Если каталог еще не указан в списке, он добавляется в файл my_list.txt

В одной строке: check="/tmp/newdirectory"; [[ -n $(grep "^$check\$" my_list.txt) ]] && echo "dir already listed" || echo "$check" >> my_list.txt

Ответ 7

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

if grep -xq "LINE_TO_BE_MATCHED" FILE_TO_LOOK_IN ; then
  # code for if it exists
else
  # code for if it does not exist
fi  

Ответ 8

Моя версия с использованием fgrep

  FOUND=`fgrep -c "FOUND" $VALIDATION_FILE`
  if [ $FOUND -eq 0 ]; then
    echo "Not able to find"
  else
    echo "able to find"     
  fi  

Ответ 9

grep -E "(string)" /path/to/file || echo "no match found"
Параметр

-E позволяет использовать регулярные выражения grep

Ответ 10

Решение grep-less работает для меня:

MY_LIST=$( cat /path/to/my_list.txt )



if [[ "${MY_LIST}" == *"${NEW_DIRECTORY_NAME}"* ]]; then
  echo "It there!"
else
echo "its not there"
fi

на основе: fooobar.com/questions/833/...

Ответ 11

grep -Fxq "String to be found" | ls -a
  • grep will поможет вам проверить содержимое
  • ls перечислит все файлы

Ответ 12

if grep -q "$Filename$" my_list.txt
   then
     echo "exist"
else 
     echo "not exist"
fi