Chciałbym sprawdzić, czy ciąg zaczyna się od „węzła”, np. „Węzła001”. Coś jak
if [ $HOST == user* ]
then
echo yes
fi
Jak mogę to zrobić poprawnie?
Ponadto muszę połączyć wyrażenia, aby sprawdzić, czy HOST to „użytkownik1” lub zaczyna się od „węzeł”
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
> > > -bash: [: too many arguments
Jak mogę to zrobić poprawnie?
string
bash
comparison
Tim
źródło
źródło
Odpowiedzi:
Ten fragment w Advanced Bash Scripting Guide mówi:
Więc miałeś prawie poprawną; potrzebowaliście podwójnych nawiasów, a nie pojedynczych nawiasów.
W odniesieniu do drugiego pytania możesz napisać to w następujący sposób:
Który odbije się echem
if
Trudno się przyzwyczaić do składni Basha (IMO).źródło
[[ $a == z* ]]
i[[ $a == "z*" ]]
? Innymi słowy: czy działają inaczej? A co konkretnie masz na myśli, mówiąc „$ a jest równe z *”?[[ $a == *com ]]
Jeśli używasz najnowszej wersji Bash (v3 +), proponuję operator porównania wyrażeń regularnych Bash
=~
, na przykład:Aby dopasować
this or that
wyrażenie regularne, użyj|
na przykład:Uwaga - jest to „właściwa” składnia wyrażeń regularnych.
user*
oznaczause
i zero lub więcej wystąpieńr
, więcuse
iuserrrr
będzie pasować.user.*
środkiuser
i zero-or-więcej wystąpień dowolnego znaku, takuser1
,userX
będzie pasował.^user.*
oznacza dopasowanie wzorcauser.*
na początku $ HOST.Jeśli nie znasz składni wyrażeń regularnych, spróbuj odwołać się do tego zasobu .
źródło
=~
operator Bash dopasowuje wyrażenie regularne tylko wtedy, gdy prawa strona jest UNQUOTED. Jeśli zacytujesz prawą stronę: „Można zacytować dowolną część wzoru, aby wymusić dopasowanie go jako łańcucha”. (1.) upewnij się, że zawsze umieszczasz wyrażenia regularne po prawej stronie bez cudzysłowu i (2.) jeśli przechowujesz swoje wyrażenie regularne w zmiennej, pamiętaj, aby NIE podawać prawej strony podczas wykonywania interpretacji parametrów.Zawsze staram się trzymać POSIX
sh
zamiast używać rozszerzeń Bash, ponieważ jednym z głównych punktów skryptów jest przenośność (oprócz łączenia programów, a nie ich zastępowania).W
sh
istnieje łatwy sposób sprawdzić dla „is-prefix” stanie.Biorąc pod uwagę wiek, tajemny i kruchy sh (a Bash nie jest lekarstwem: jest bardziej skomplikowany, mniej spójny i mniej przenośny), chciałbym zwrócić uwagę na bardzo fajny aspekt funkcjonalny: chociaż niektóre elementy składniowe
case
są wbudowane , powstałe konstrukcje nie różnią się niczym od innych zadań. Można je składać w ten sam sposób:Lub nawet krócej
Lub nawet krócej (tylko
!
jako element językowy - ale teraz jest to zły styl)Jeśli lubisz wyrażać się jasno, zbuduj swój własny element językowy:
Czy to nie jest całkiem miłe?
A ponieważ
sh
zasadniczo są to tylko zadania i listy ciągów (i procesy wewnętrzne, z których składają się zadania), możemy teraz nawet wykonać lekkie programowanie funkcjonalne:To jest eleganckie. Nie, że zalecałbym używanie
sh
do czegoś poważnego - zbyt szybko psuje się w rzeczywistych wymaganiach (brak lambd, więc musimy używać łańcuchów. Ale zagnieżdżanie wywołań funkcji za pomocą łańcuchów nie jest możliwe, potoki nie są możliwe itp.)źródło
case $HOST in user01 | node* ) ...
if case $HOST in node*) true;; *) false;; esac; then
Widziałem to tu i tam, dla mnie wygląda to na trochę zgniecione.case
polecenia są poleceniami, mogą wejść do środkaif ... then
.beginswith() { case "$2" in "$1"*) true;; *) false;; esac; }
inaczej powinno być, jeśli$1
ma literał*
lub?
może dać złą odpowiedź.Możesz wybrać tylko część ciągu, którą chcesz sprawdzić:
W kolejnym pytaniu możesz użyć OR :
źródło
${HOST:0:4}
HOST='a b'; if [ ${HOST:0:4} = user ] ; then echo YES ; fi
Wolę inne metody już opublikowane, ale niektórzy ludzie lubią używać:
Edytować:
Dodałem twoje alternatywy do powyższego oświadczenia
W edytowanej wersji masz za dużo nawiasów. To powinno wyglądać tak:
źródło
Chociaż uważam, że większość odpowiedzi tutaj jest całkiem poprawna, wiele z nich zawiera niepotrzebne Bashizmy. Rozszerzenie parametrów POSIX zapewnia wszystko, czego potrzebujesz:
i
${var#expr}
usuwa najmniejsze dopasowanie przedrostkaexpr
z${var}
i zwraca to. Stąd jeśli${host}
nie nie zaczynaćuser
(node
),${host#user}
(${host#node}
) jest taka sama jak${host}
.expr
pozwala na stosowaniefnmatch()
symboli wieloznacznych,${host#node??}
a zatem i przyjaciele również działają.źródło
[[ $host == user* ]]
że bashizm może być konieczny, ponieważ jest o wiele bardziej czytelny niż[ "${host#user}" != "${host}" ]
. Jako że pod warunkiem, że kontrolujesz środowisko, w którym skrypt jest wykonywany (celuj w najnowsze wersjebash
), to pierwsze jest preferowane.has_prefix()
funkcję i nigdy więcej na nią nie spojrzę.Od
#
ma to znaczenie w Bash, doszedłem do następującego rozwiązania.Ponadto wolę spakować ciągi znaków „”, aby pokonać spacje itp.
źródło
blah:
, wygląda na to, że to jest odpowiedź!Dodając nieco więcej szczegółów składniowych do najwyższej odpowiedzi Marka Rushakoffa.
Ekspresja
Można również zapisać jako
Efekt jest taki sam. Upewnij się tylko, że symbol wieloznaczny znajduje się poza cytowanym tekstem. Jeśli symbol wieloznaczny znajduje się w cudzysłowie, będzie interpretowany dosłownie (tj. Nie jako symbol wieloznaczny).
źródło
@OP, w obu pytaniach możesz użyć case / esac:
Drugie Pytanie
Lub Bash 4.0
źródło
;&
jest dostępne tylko w Bash> = 4.nie działa, ponieważ wszystkie
[
,[[
itest
rozpoznać tę samą gramatykę nierekurencyjnym. Patrz sekcja WYRAŻENIA WARUNKOWE na stronie użytkownika Bash.Nawiasem mówiąc, SUSv3 mówi
Musisz napisać to w ten sposób, ale test go nie obsługuje:
test używa = do równości łańcuchów, a co ważniejsze, nie obsługuje dopasowania wzorca.
case
/esac
ma dobre wsparcie dla dopasowania wzorca:Ma tę dodatkową zaletę, że nie zależy od Bash, a składnia jest przenośna. Ze specyfikacji Single Unix , język poleceń powłoki :
źródło
[
itest
są wbudowane w Bash, a także programy zewnętrzne. Spróbowaćtype -a [
.if [ -z $aa -or -z $bb ]
; ... daje „ bash: [: -or: operator binarny oczekiwany ”; jednakif [ -z "$aa" -o -z "$bb" ] ; ...
mija.grep
Zapominając o wydajności, jest to POSIX i wygląda ładniej niż
case
rozwiązania:Wyjaśnienie:
printf '%s'
aby zapobiecprintf
rozszerzaniu znaków ucieczki z odwrotnym ukośnikiem: Bash printf dosłowny ciąg dosłownygrep -q
zapobiega echu dopasowań na standardowe wyjście: Jak sprawdzić, czy plik zawiera określony ciąg za pomocą Bashgrep -E
włącza rozszerzone wyrażenia regularne, których potrzebujemy^
źródło
Poprawiłem odpowiedź @ markrushakoff, aby stała się funkcją wywoływalną:
Użyj tego w ten sposób:
Oto bardziej złożona wersja, która zapewnia określoną wartość domyślną:
Użyj tego w ten sposób:
źródło
Inną rzeczą, którą możesz zrobić, jest
cat
wyjście z echa i potokówinline cut -c 1-1
źródło