Mam kod
file="JetConst_reco_allconst_4j2t.png"
if [[ $file == *_gen_* ]];
then
echo "True"
else
echo "False"
fi
Sprawdzam, czy file
zawiera „gen”. Wynikiem jest „False”. Miły!
Problem polega na tym, że podstawiam „gen” zmienną testseq
:
file="JetConst_reco_allconst_4j2t.png"
testseq="gen"
if [[ $file == *_$testseq_* ]];
then
echo "True"
else
echo "False"
fi
Teraz wyjście ma wartość „True”. Jak to mogło się stać? Jak rozwiązać problem?
shell-script
variable
string
control-flow
Viesturs
źródło
źródło
Odpowiedzi:
Musisz interpolować
$testseq
zmienną na jeden z następujących sposobów:$file == *_"$testseq"_*
(tutaj$testseq
uważany za stały ciąg)$file == *_${testseq}_*
(tutaj$testseq
uważany za wzór).Lub
_
bezpośrednio po nazwie zmiennej zostanie wzięty jako część nazwy zmiennej (jest to prawidłowy znak w nazwie zmiennej).źródło
Użyj
=~
operatora, aby wykonać porównania wyrażeń regularnych:W ten sposób porówna, jeśli
$file
ma$testseq
na swojej zawartości.Jeśli zmienię
testseq="Const"
:Ale uważaj na to, co karmisz
$testseq
. Jeśli ciąg znaków na nim reprezentuje wyrażenie regularne (jak[0-9]
na przykład), istnieje większa szansa na wywołanie „dopasowania”.Odniesienie :
źródło
Używanie
case ... esac
jest jednym z najprostszych sposobów wykonania dopasowania wzorca w przenośny sposób. Działa jako instrukcja „switch” w innych językach (bash
,zsh
aksh93
także pozwala na awarię na różne niekompatybilne sposoby). Zastosowane wzorce to standardowe wzorce globowania nazw plików.Problem, który masz, wynika z faktu, że
_
jest to prawidłowy znak w nazwie zmiennej. Powłoka będzie zatem widzieć*_$testseq_*
jako „*_
po wartości zmiennej$testseq_
i*
”. Zmienna$testseq_
jest niezdefiniowana, więc zostanie rozwinięta do pustego łańcucha, a na końcu skończy się*_*
, co oczywiście pasuje do$file
wartości, którą masz. Możesz się spodziewać,True
że nazwa pliku$file
zawiera co najmniej jeden znak podkreślenia.Aby właściwie ograniczają nazwę zmiennej, użytkowania
"..."
wokół rozbudowy:*_"$testseq"_*
. Użyłoby to wartości zmiennej jako łańcucha. Jeśli chcesz użyć wartości zmiennej jako wzorca , użyj*_${testseq}_*
zamiast tego.Innym szybkim rozwiązaniem jest uwzględnienie podkreślników w wartości
$testseq
:a następnie po prostu użyj
*"$testseq"*
jako wzorca (do porównania łańcucha).źródło
*"$testseq"*
dlacase
jak dla[[...]]
(z wyjątkiem zsh chyba że włączysz globsubst)