Mam plik zawierający nazwy katalogów:
my_list.txt
:
/tmp
/var/tmp
Chciałbym sprawdzić w Bash, zanim dodam nazwę katalogu, jeśli ta nazwa już istnieje w pliku.
Mam plik zawierający nazwy katalogów:
my_list.txt
:
/tmp
/var/tmp
Chciałbym sprawdzić w Bash, zanim dodam nazwę katalogu, jeśli ta nazwa już istnieje w pliku.
Odpowiedzi:
grep -Fxq "$FILENAME" my_list.txt
Status wyjścia to 0 (prawda), jeśli nazwa została znaleziona, 1 (fałsz), jeśli nie, więc:
if grep -Fxq "$FILENAME" my_list.txt
then
# code if found
else
# code if not found
fi
Oto odpowiednie sekcje strony podręcznika dlagrep
:
grep [options] PATTERN [FILE...]
-F
,--fixed-strings
Interpretuj WZÓR jako listę stałych ciągów, oddzielonych znakami nowej linii, z których każda ma zostać dopasowana.
-x
,--line-regexp
Wybierz tylko te dopasowania, które dokładnie pasują do całej linii.
-q
,--quiet
,--silent
Cichy; nie pisz niczego na standardowe wyjście. Wyjdź natychmiast ze statusem zero, jeśli zostanie znalezione dopasowanie, nawet jeśli wykryty zostanie błąd. Zobacz także opcję
-s
lub--no-messages
.
Jak słusznie wskazano w komentarzach, powyższe podejście po cichu traktuje przypadki błędów tak, jakby ciąg został znaleziony. Jeśli chcesz obsługiwać błędy w inny sposób, musisz pominąć tę -q
opcję i wykryć błędy na podstawie stanu wyjścia:
Zwykle stan wyjścia wynosi 0, jeśli zostaną znalezione wybrane linie, a w przeciwnym razie 1. Ale stan wyjścia to 2, jeśli wystąpił błąd, chyba że użyto opcji
-q
lub--quiet
lub--silent
i znaleziono wybraną linię. Należy jednak pamiętać, że tylko POSIX mandaty dla programów takich jakgrep
,cmp
orazdiff
, że stan wyjście w przypadku błędu być większa niż 1; dlatego zaleca się, ze względu na przenośność, zastosować logikę, która sprawdza ten ogólny warunek zamiast ścisłej równości z 2.
Aby stłumić normalne wyjście grep
, możesz przekierować je na /dev/null
. Zauważ, że standardowy błąd nie jest przekierowywany, więc wszelkie komunikaty o błędach, które grep
mogą zostać wydrukowane, trafią na konsolę, tak jak zapewne chcesz.
Aby obsłużyć trzy przypadki, możemy użyć case
instrukcji:
case `grep -Fx "$FILENAME" "$LIST" >/dev/null; echo $?` in
0)
# code if found
;;
1)
# code if not found
;;
*)
# code if an error occurred
;;
esac
$?
. możesz także użyć polecenia grep obok if
instrukcji (jak pokazano w zaktualizowanej odpowiedzi).
grep -Fqx "$FILENAME"
i nie musisz się martwić o wyrażenia regularne w treści zmiennej i nie będziesz musiał ich używać w ciągu wyszukiwania.
-q / --silent
jest to potrzebne? Fałszywie mówi „wszystko dobre”, aby walić, nawet jeśli wystąpi błąd. Jeśli dobrze to zrozumiałem. Wydaje się, że w tej sprawie jest błędna koncepcja.
W odniesieniu do następującego rozwiązania:
grep -Fxq "$FILENAME" my_list.txt
Jeśli zastanawiasz się (tak jak ja), co -Fxq
oznacza zwykły angielski:
F
: Wpływa na sposób interpretacji WZORCA (stały ciąg zamiast wyrażenia regularnego)x
: Dopasuj całą linięq
: Ciii… minimalne drukowanieZ pliku 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.)
Trzy metody w mojej głowie:
1) Krótki test nazwy na ścieżce (nie jestem pewien, czy to może być twój przypadek)
ls -a "path" | grep "name"
2) Krótki test na ciąg znaków w pliku
grep -R "string" "filepath"
3) Dłuższy skrypt bashowy, używając wyrażenia regularnego:
#!/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
Powinno to być szybsze, jeśli trzeba przetestować wiele ciągów znaków na zawartości pliku za pomocą pętli, na przykład zmieniając wyrażenie regularne w dowolnym wierszu.
Prostszy sposób:
if grep "$filename" my_list.txt > /dev/null
then
... found
else
... not found
fi
Wskazówka: wyślij, /dev/null
jeśli chcesz status wyjścia polecenia, ale nie wyjścia.
-q
tego samego, co --quiet
:)
-q
również na najlepszą odpowiedź tutaj i jest czwarte miejsce. brak sprawiedliwości na tym świecie.
Najłatwiejszym i najprostszym sposobem byłoby:
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 zwróci liczbę, ile razy łańcuch występuje w pliku.
Jeśli dobrze zrozumiałem twoje pytanie, powinno zrobić to, czego potrzebujesz.
W jednej linii :check="/tmp/newdirectory"; [[ -n $(grep "^$check\$" my_list.txt) ]] && echo "dir already listed" || echo "$check" >> my_list.txt
grep -q
grep i wywołać go bezpośrednio, if
jak robi to Thomas w swojej odpowiedzi. Ponadto pytanie nie obejmowało sprawdzenia, czy katalog istnieje przed dodaniem go do listy (w końcu może to być lista usuniętych katalogów).
grep -E "(string)" /path/to/file || echo "no match found"
-E opcja powoduje, że grep używa wyrażeń regularnych
Rozwiązanie @ Thomas z jakiegoś powodu nie działało, ale miałem dłuższy ciąg znaków specjalnych i białych znaków, więc zmieniłem tylko następujące parametry:
if grep -Fxq 'string you want to find' "/path/to/file"; then
echo "Found"
else
echo "Not found"
fi
Mam nadzieję, że to komuś pomoże
Rozwiązanie bez grepa, działa dla mnie:
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
na podstawie: https://stackoverflow.com/a/229606/3306354
grep -q
opisane w przyjętej odpowiedzi jest najbardziej efektywnym podejściem.
grep -Fxq "String to be found" | ls -a