У мене є файл, який містить імена каталогів:
my_list.txt
:
/tmp
/var/tmp
Я хотів би зареєструватися в Bash перед тим, як додати ім'я каталогу, якщо це ім’я вже існує у файлі.
У мене є файл, який містить імена каталогів:
my_list.txt
:
/tmp
/var/tmp
Я хотів би зареєструватися в Bash перед тим, як додати ім'я каталогу, якщо це ім’я вже існує у файлі.
Відповіді:
grep -Fxq "$FILENAME" my_list.txt
Статус виходу 0 (вірно), якщо ім'я знайдено, 1 (помилково), якщо ні, значить:
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
$?
. ви також можете використовувати команду grep поряд із if
твердженням (як показано в оновленій відповіді).
grep -Fqx "$FILENAME"
і вам не доведеться турбуватися про символи регулярного виразів у змінній змісті, і вам не доведеться використовувати їх у пошуковій рядку.
-q / --silent
це потрібно? Це помилково говорить "все добре", щоб ударити, навіть якщо помилка. Якщо я це зрозумів правильно. Здається, в цьому випадку недосконала концепція.
Щодо наступного рішення:
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.)
Три мої думки:
1) Короткий тест на ім’я в контурі (я не впевнений, що це може бути у вашому випадку)
ls -a "path" | grep "name"
2) Короткий тест на рядок у файлі
grep -R "string" "filepath"
3) Більш довгий скрипт за допомогою регулярного вираження:
#!/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
Це повинно бути швидше, якщо вам доведеться протестувати кілька рядків на вміст файлу, використовуючи цикл, наприклад, змінивши регулярний вираз на будь-якому файлі.
Простіший спосіб:
if grep "$filename" my_list.txt > /dev/null
then
... found
else
... not found
fi
Порада: надішліть, /dev/null
якщо ви хочете статус виходу команди, але не виходи.
-q
саме, що --quiet
:)
-q
також на найкращу відповідь тут, і це четверте місце. немає справедливості в цьому світі.
Найпростішим і найпростішим способом було б:
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 поверне кількість підрахунків, скільки разів в рядку виникає рядок.
Якщо я правильно зрозумів ваше запитання, це повинно робити все, що вам потрібно.
В одному рядку :check="/tmp/newdirectory"; [[ -n $(grep "^$check\$" my_list.txt) ]] && echo "dir already listed" || echo "$check" >> my_list.txt
grep -q
та дзвонити grep безпосередньо з так, if
як це робить Томас у своїй відповіді. Крім того, питання не включало перевірку існування каталогу перед тим, як додати його до списку (це може бути список видалених каталогів, зрештою).
grep -E "(string)" /path/to/file || echo "no match found"
-E варіант змушує grep використовувати регулярні вирази
Рішення @ Thomas чомусь не працювало для мене, але у мене була довша рядок зі спеціальними символами та пробілами, тому я просто змінив такі параметри:
if grep -Fxq 'string you want to find' "/path/to/file"; then
echo "Found"
else
echo "Not found"
fi
Сподіваюся, це комусь допоможе
Для мене працює безвідступне рішення:
MY_LIST=$( cat /path/to/my_list.txt )
if [[ "${MY_LIST}" == *"${NEW_DIRECTORY_NAME}"* ]]; then
echo "It's there!"
else
echo "its not there"
fi
на основі: https://stackoverflow.com/a/229606/3306354
grep -q
описаний у прийнятій відповіді є найбільш ефективним підходом.
grep -Fxq "String to be found" | ls -a