Test om en streng indeholder en understreng

Jeg har koden

file="JetConst_reco_allconst_4j2t.png" if [[ $file == *_gen_* ]]; then echo "True" else echo "False" fi 

I test hvis file indeholder “gen”. Outputtet er “Falsk”. Dejligt!

Problemet er, når jeg erstatter “gen” med en variabel testseq:

file="JetConst_reco_allconst_4j2t.png" testseq="gen" if [[ $file == *_$testseq_* ]]; then echo "True" else echo "False" fi 

Nu er output “sandt”. Hvordan kunne det være? Sådan løses problemet?

Kommentarer

Svar

Du skal interpolere $testseq variabel med en af følgende måder:

  • $file == *_"$testseq"_* (her $testseq betragtes som en fast streng)

  • $file == *_${testseq}_* (her $testseq betragtes som et mønster).

Eller _ umiddelbart efter variabelens navn tages som en del af variablen “s navn (det er et gyldigt tegn i et variabelnavn).

Kommentarer

  • Korrekt svar, da det gælder for OP, men uden at være bærbart . (Dette er ingen kritik af det leverede svar, bare en advarsel til læserne). 😉

Svar

Brug =~ operat eller for at lave sammenligninger med regelmæssigt udtryk:

#!/bin/bash file="JetConst_reco_allconst_4j2t.png" testseq="gen" if [[ $file =~ $testseq ]]; then echo "True" else echo "False" fi 

På denne måde sammenlignes det, hvis $file har $testseq om dets indhold.

user@host:~$ ./string.sh False 

Hvis jeg ændrer testseq="Const":

user@host:~$ ./string.sh True 

Men pas på, hvad du fodrer $testseq med. Hvis strengen på den på en eller anden måde repræsenterer en regex (som f.eks. [0-9]), er der en større chance for at udløse et “match”.

Reference :

Kommentarer

  • Det ser ud til, at dette svar er til " bash "

Svar

file="JetConst_reco_allconst_4j2t.png" testseq="gen" case "$file" in *_"$testseq"_*) echo "True" ;; *) echo "False" esac 

Brug af case ... esac er en af de enkleste måder at udføre et mønstermatch på en bærbar måde. Det fungerer som en “switch” -erklæring på andre sprog (bash, zsh og ksh93 giver dig også mulighed for at udføre gennemslag på forskellige uforenelige måder). De anvendte mønstre er standardfilnavnet globmønstre.

Det problem, du har, skyldes, at _ er et gyldigt tegn i et variabelt navn. Skallen vil således se *_$testseq_* som “*_ efterfulgt af værdien af variablen $testseq_ og en * “. Variablen $testseq_ er udefineret, så den udvides til en tom streng, og du ender med *_*, som naturligvis matcher $file værdi, du har. Du kan forvente at få True så længe filnavnet i $file indeholder mindst en understregning.

For korrekt afgrænse navnet på variablen, brug "..." omkring udvidelsen: *_"$testseq"_*. Dette vil bruge værdien af variablen som en streng. Vil du bruge værdien af variablen som et mønster , skal du bruge *_${testseq}_* i stedet.

En anden hurtig løsning er at inkludere understreger værdien af $testseq:

testseq="_gen_" 

og brug derefter bare *"$testseq"* som mønster (til en strengesammenligning).

Kommentarer

  • Så shell vil være på udkig efter en variabel $ testseq_ og ikke finde udskift det med en tom streng.
  • @Viesturs At ' s er kernen i problemet, ja.
  • For en substringsøgning skal være *"$testseq"* for case som for [[...]] (undtagen zsh, medmindre du aktiver globsubst)
  • Enklere end [ "${str##*substr*}" ] || echo True?
  • @Isaac Med hensyn til læsning og forståelse af hvad ' s sker, ja. ' er også let at udvide en test med flere testsager uden at få en " if-then-elif-then-elif " spaghetti. Selvom du tester en enkelt streng, som du viser (om en streng forsvinder i en erstatning), er kortere.

Svar

For den bærbare måde at teste, om en streng indeholder en understreng, skal du bruge:

file="JetConst_reco_allconst_4j2t.png"; testseq="gen" [ "${file##*$testseq*}" ] || echo True Substring is present 

Eller "${file##*"$testseq"*}" for at undgå at fortolke globaltegn i testseq.

Kommentarer

  • Du ' har brug for noget som [" $ {file ## * $ testseq *} "! = " $ file " ] fordi i bindestreg, der er Fjern største præfiks mønster.
  • Nej, @NoelGrandin er der ingen ændring på de fleste skaller (inklusive bindestreg), Største præfiks mønster vil være hele strengen hvis den variable submønster ($testseq) værdi er indeholdt i værdien $file. Prøv: dash -c 'file="JetConst_reco_allconst_4j2t.png"; testseq="reco"; echo "=${file##*"$testseq"*}="' for at bekræfte, at bindestreg fjerner hele strengen.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *