W bash, Jak mogę sprawdzić, czy ciąg zaczyna się od jakiejś wartości?
Chciałbym sprawdzić, czy łańcuch zaczyna się od "node" np. "node001". Coś jak
if [ $HOST == user* ]
then
echo yes
fi
Jak mogę to zrobić poprawnie?
Muszę jeszcze połączyć wyrażenia, aby sprawdzić, czy HOST jest albo "user1", albo zaczyna się od"node"
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
> > > -bash: [: too many arguments
Jak to zrobić poprawnie?
11 answers
Ten fragment w Advanced Bash Scripting Guide mówi:
# The == comparison operator behaves differently within a double-brackets
# test than within single brackets.
[[ $a == z* ]] # True if $a starts with a "z" (wildcard matching).
[[ $a == "z*" ]] # True if $a is equal to z* (literal matching).
Więc miałeś prawie poprawnie; potrzebowałeś podwójnych nawiasów, a nie pojedynczych nawiasów.
Jeśli chodzi o twoje drugie pytanie, możesz napisać je w ten sposób:
HOST=user1
if [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
echo yes1
fi
HOST=node001
if [[ $HOST == user1 ]] || [[ $HOST == node* ]] ;
then
echo yes2
fi
Które będą echo
yes1
yes2
Składnia Basha if
jest trudna do przyzwyczajenia (IMO).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-26 10:17:11
Jeśli używasz najnowszej wersji bash (v3+) sugeruj operator porównywania regex bash =~
, tzn.
if [[ "$HOST" =~ ^user.* ]]; then
echo "yes"
fi
Aby dopasować this or that
w regex use |
, tzn.
if [[ "$HOST" =~ ^user.*|^host1 ]]; then
echo "yes"
fi
Uwaga-jest to 'właściwa' składnia wyrażenia regularnego.
-
user*
oznaczause
i zero-lub-więcej wystąpieńr
, więcuse
iuserrrr
będą pasować. -
user.*
oznaczauser
i zero-lub-więcej wystąpień dowolnego znaku, więcuser1
,userX
pasuje. -
^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.
Uwaga-lepiej jest zadawać każde nowe pytanie jako nowe pytanie, czyni stackoverflow bardziej uporządkowanym i użytecznym. Zawsze możesz podać link do poprzedniego pytania w celach informacyjnych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-09 12:26:37
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, jest łatwy sposób, aby sprawdzić warunek "is-prefix".
case $HOST in node*)
your code here
esac
Biorąc pod uwagę, jak stary, arcane i crufty sh jest (a bash nie jest lekarstwem: jest bardziej skomplikowany, mniej spójny i mniej przenośny), chciałbym zwrócić uwagę na bardzo ładny aspekt funkcjonalny: podczas gdy niektóre składnie elementy takie jak case
są wbudowane, powstałe konstrukcje nie różnią się od innych zadań. Można je składać w ten sam sposób:
if case $HOST in node*) true;; *) false;; esac; then
your code here
fi
Lub nawet krótszy
if case $HOST in node*) ;; *) false;; esac; then
your code here
fi
Lub nawet krótszy (aby przedstawić !
jako element języka - ale teraz jest to zły styl)
if ! case $HOST in node*) false;; esac; then
your code here
fi
Jeśli lubisz być jawny, Zbuduj swój własny element języka:
beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
Czy to nie całkiem miłe?
if beginswith node "$HOST"; then
your code here
fi
A ponieważ SH to w zasadzie tylko jobs i string-list (i procesy wewnętrzne, z których składają się zadania), możemy teraz nawet wykonać lekkie Programowanie funkcyjne: {]}
beginswith() { case $2 in "$1"*) true;; *) false;; esac; }
checkresult() { if [ $? = 0 ]; then echo TRUE; else echo FALSE; fi; }
all() {
test=$1; shift
for i in "$@"; do
$test "$i" || return
done
}
all "beginswith x" x xy xyz ; checkresult # prints TRUE
all "beginswith x" x xy abc ; checkresult # prints FALSE
To jest eleganckie. Nie żebym opowiadał się za używaniem sh do czegokolwiek poważnego . łamie się zbyt szybko na realnych wymaganiach (bez lambda, więc trzeba używać stringów. Ale zagnieżdżanie wywołań funkcji z łańcuchami nie jest możliwe, rury nie są możliwe...)Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-10 19:08:02
Możesz wybrać tylko część łańcucha, którą chcesz sprawdzić:
if [ ${HOST:0:4} = user ]
Do pytania uzupełniającego możesz użyć lub:
if [[ $HOST == user1 || $HOST == node* ]]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-31 16:53:46
Wolę inne metody już zamieszczone, ale niektórzy lubią używać:
case "$HOST" in
user1|node*)
echo "yes";;
*)
echo "no";;
esac
Edit:
Dodałem Twoich zastępców do powyższej wypowiedzi
W edytowanej wersji masz za dużo nawiasów. Powinno to wyglądać tak:
if [[ $HOST == user1 || $HOST == node* ]];
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-31 17:43:20
Ponieważ # ma znaczenie w bashu, doszedłem do następującego rozwiązania.
Poza tym wolę pakować struny z "" do pokonywania spacji itp.
A="#sdfs"
if [[ "$A" == "#"* ]];then
echo "skip comment line"
fi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-01 09:11:35
Chociaż większość odpowiedzi tutaj jest całkiem poprawna, wiele z nich zawiera niepotrzebne bashismsy. rozszerzenie parametru POSIX daje Ci wszystko, czego potrzebujesz:
[ "${host#user}" != "${host}" ]
I
[ "${host#node}" != "${host}" ]
${var#expr}
usuwa najmniejszy przedrostek pasujący do expr
z ${var}
i zwraca go. Stąd Jeśli ${host}
nie zaczyna się od user
(node
), ${host#user}
(${host#node}
) jest tym samym co ${host}
.
expr
pozwala fnmatch()
wildcards, więc ${host#node??}
i przyjaciele również działają.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-06 13:02:47
@OP, do obu pytań możesz użyć case / esac
string="node001"
case "$string" in
node*) echo "found";;
* ) echo "no node";;
esac
Pytanie drugie]}
case "$HOST" in
node*) echo "ok";;
user) echo "ok";;
esac
case "$HOST" in
node*|user) echo "ok";;
esac
Lub Bash 4.0
case "$HOST" in
user) ;&
node*) echo "ok";;
esac
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-01 13:48:59
if [ [[ $HOST == user1 ]] -o [[ $HOST == node* ]] ];
then
echo yes
fi
Nie działa, ponieważ wszystkie [, [[ i test rozpoznać tę samą gramatykę nieekursywną. patrz sekcja wyrażenia warunkowe na stronie podręcznika bash.
Na marginesie, SUSv3 mówi
Wywołanie warunkowe Kornshella (podwójny nawias [[]]) został usunięty z opisu języka poleceń powłoki we wczesnej propozycji. Pojawiły się zastrzeżenia, że prawdziwym problemem jest niewłaściwe wykorzystanie testu dowództwo ([), a umieszczenie go w powłoce to zły sposób na rozwiązanie problemu. Zamiast tego, Odpowiednia dokumentacja i nowe słowo zarezerwowane powłoki (!) są wystarczające.
Testy wymagające wielu operacji test mogą być wykonywane na poziomie powłoki przy użyciu pojedynczych wywołań polecenia test i logicali powłoki, zamiast używać podatnego na błędy znacznika -o z test.
Trzeba by to tak napisać, ale test nie obsługuje:
if [ $HOST == user1 -o $HOST == node* ];
then
echo yes
fi
test zastosowania = dla równości ciągów, co ważniejsze, nie obsługuje dopasowania wzorców.
case
/ esac
ma dobre wsparcie dla dopasowania wzorca:
case $HOST in
user1|node*) echo yes ;;
esac
Ma dodatkową zaletę, że nie zależy od Basha, składnia jest przenośna. z pojedynczej specyfikacji Uniksa, język poleceń powłoki:
case word in
[(]pattern1) compound-list;;
[[(]pattern[ | pattern] ... ) compound-list;;] ...
[[(]pattern[ | pattern] ... ) compound-list]
esac
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-01 15:33:58
Dodanie trochę więcej szczegółów składni do odpowiedzi Mark Rushakoff najwyższej rangi.
Wyrażenie
$HOST == node*
Można również zapisać jako
$HOST == "node"*
Efekt jest taki sam. Upewnij się tylko, że symbol wieloznaczny znajduje się poza cytowanym tekstem. Jeśli symbol wieloznaczny jest wewnątrz cudzysłowów, będzie on interpretowany dosłownie (tzn. nie jako symbol wieloznaczny).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-06 05:15:00
Kolejna rzecz, którą możesz zrobić to cat
out what you are echoing and pipe with inline cut -c 1-1
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-28 00:06:28