Megvan a kódom
file="JetConst_reco_allconst_4j2t.png" if [[ $file == *_gen_* ]]; then echo "True" else echo "False" fi
Tesztelek ha a file
tartalmazza a “gen” szót. A kimenet “hamis”. Szép!
A probléma az, amikor a “gen” szót egy testseq
változóval helyettesítem:
file="JetConst_reco_allconst_4j2t.png" testseq="gen" if [[ $file == *_$testseq_* ]]; then echo "True" else echo "False" fi
Most a kimenet “True”. Hogy lehetséges ez? Hogyan lehet kijavítani a problémát?
Megjegyzések
- A Shell teszt lehetséges másolata a minta megtalálásához karakterláncban
Válasz
Interpolálni kell a $testseq
változó a következő módok egyikével:
-
$file == *_"$testseq"_*
(itt$testseq
rögzített karakterláncnak tekinthető) -
$file == *_${testseq}_*
(itt$testseq
egy minta).
Vagy a _
közvetlenül a változó neve után bekerül a változó s részébe név (ez egy érvényes karakter egy változó nevében).
Megjegyzések
- Helyes válasz, mivel az OP-ra vonatkozik, de nem hordozható . (Ez nem a megadott válasz kritikája, csupán figyelmeztetés az olvasókra). 😉
Válasz
Használja a =~
operát vagy rendszeres kifejezés-összehasonlítások:
#!/bin/bash file="JetConst_reco_allconst_4j2t.png" testseq="gen" if [[ $file =~ $testseq ]]; then echo "True" else echo "False" fi
Így összehasonlítja, ha a $file
$testseq
tartalmát.
user@host:~$ ./string.sh False
Ha megváltoztatom a következőt: testseq="Const"
:
user@host:~$ ./string.sh True
De vigyázzon azzal, amit $testseq
táplál. Ha a rajta lévő karakterlánc valamilyen módon egy regexet képvisel (például [0-9]
), akkor nagyobb az esély a “mérkőzés” kiváltására.
Hivatkozás :
megjegyzések
- Úgy tűnik, hogy ez a válasz a " bash "
válasz
file="JetConst_reco_allconst_4j2t.png" testseq="gen" case "$file" in *_"$testseq"_*) echo "True" ;; *) echo "False" esac
A case ... esac
használata az egyik legegyszerűbb módszer a mintaillesztés hordozható módon történő végrehajtására. “Switch” utasításként működik más nyelveken (bash
, zsh
és ksh93
azt is lehetővé teszi, hogy átesést végezzenek, különböző kompatibilis módon). A felhasznált minták a szokásos fájlnévi hullámzó minták.
A probléma annak a ténynek tudható be, hogy a _
egy érvényes karakter egy változónévben. A héj tehát *_$testseq_*
-et “*_
néven fogja látni, amelyet a $testseq_
változó értéke követ. és egy *
“. A $testseq_
változó nincs meghatározva, ezért kibővül egy üres karakterláncra, és végül a *_*
változóra kerül, ami nyilvánvalóan megegyezik a $file
értéke. Arra számíthat, hogy True
megkapja, amennyiben a $file
fájlnév legalább egy aláhúzást tartalmaz.
A megfelelő működéshez határozza meg a változó nevét, használja a "..."
elemet a kibővítés körül: *_"$testseq"_*
. Ez a változó értékét karakterláncként használná. Szeretné a változó értékét mintaként használni, használja helyette az *_${testseq}_*
szót.
Egy másik gyors javítás a aláhúzza az $testseq
értékét:
testseq="_gen_"
, majd csak használja a *"$testseq"*
mint a minta (a karakterláncok összehasonlításához).
Megjegyzések
- Tehát a shell a $ testseq_ változót keresi, és nem fogja megtalálni és helyettesítsen egy üres karakterlánccal.
- @Viesturs Ez a ' s a kérdés középpontjában, igen.
- Egy alkönyvtár keresésnek
*"$testseq"*
kell lenniecase
számára, mint például a[[...]]
(kivéve a engedélyezze a globsubst engedélyezését) - Egyszerűbb, mint a
[ "${str##*substr*}" ] || echo True
? - @Isaac Mit olvasni és megérteni szempontjából ' s történik, igen. ' is könnyű egy tesztet meghosszabbítani több tesztesettel anélkül, hogy " if-then-elif-then-elif " spagetti. Bár egyetlen karakterláncot úgy tesztelhet, ahogyan megmutatja (eltűnik-e egy karakterlánc egy helyettesítésben), az rövidebb.
Válasz
A hordozható mód teszteléséhez, hogy egy karakterlánc tartalmaz-e alszöveget, használja:
file="JetConst_reco_allconst_4j2t.png"; testseq="gen" [ "${file##*$testseq*}" ] || echo True Substring is present
Vagy "${file##*"$testseq"*}"
, hogy elkerülje a globális karakterek értelmezését a testseq
.
Megjegyzések
- Szüksége van ' olyasmire, mint [" $ {file ## * $ testseq *} "! = " $ file " ], mert a kötőjelben, amely a Legnagyobb előtag minta eltávolítása.
- Nem, @NoelGrandin a legtöbb kagylóban (beleértve a kötőjelet) nincs változás, a Legnagyobb előtag minta lesz az egész karakterlánc ha a változó alminta (
$testseq
) értéke a$file
értéken belül található. Próbálja meg:dash -c 'file="JetConst_reco_allconst_4j2t.png"; testseq="reco"; echo "=${file##*"$testseq"*}="'
megerősíteni, hogy a kötőjel eltávolítja az egész karakterláncot.