Tesztelje, hogy egy karakterlánc tartalmaz-e egy alszöveget

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

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 lennie case 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.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük