2017-02-01 2 views
0

Die Regex ich gerade arbeite im Moment ist wie folgt:Regex „Beginn der Zeichenfolge“ Anker nicht funktioniert

^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$ 

Ich versuche, alle Gleitkommazahlen zu entsprechen, aber nur die Nummer. Zum Beispiel sollte die folgenden entsprechen:

  • 6,0
  • 1.22E3
  • -2
  • 2.99999e-12

Allerdings sollte die folgenden nicht überein:

  • somestring /////// 6,0

Ich habe die obige Regex auf this validation site getestet und es funktioniert wie erwartet. Wenn es in meinem Bash-Skript ausgeführt wird, stimmt jedoch nichts.

Dies ist mein bash Code:

if [[ "$VAL" =~ ^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$ ]] 
    then 
     echo $VAL, "is a number" 
    else 
     echo $VAL, "is not a number" 
fi 

Ich habe versucht, die Anker zu entfernen, und sie paßt alle Strings, die Floating-Punkte enthalten. Strings wie "//////6.00007" stimmen jedoch überein. Der $ -Anker funktioniert wie erwartet; Das tut es jedoch nicht.

Bitte lassen Sie mich wissen, wenn Sie Vorschläge zur Fehlerbehebung haben.

Danke!

bearbeiten 1

Entfernt schlechte Beispiele

bearbeiten 2

lief ich die Regex in seinem eigenen foo.sh wie @lurker vorgeschlagen und der Code lief wie bei meinem Testfälle erwartet . Also schaute ich mir an, was mit der Regex verglichen wurde. Als ich sah, was verglichen wurde, sah alles gut aus, also machte es keinen Sinn, warum die Regex nicht übereinstimmte.

Dann begann ich zu vermuten, dass echo wurde nicht angezeigt, was war eigentlich in $VAL aus irgendeinem Grund.

So lief ich das: NEWVAL=(echo $VAL) als temporäre Abhilfe, bis ich herausfinden kann, was los ist.

+2

Ich habe versucht, Ihre Regex und Skript wie es ist, und sie scheinen für mich gut zu funktionieren. '" //////6.00007 "kam heraus" ist keine Zahl ". – lurker

+0

Seltsam. Was sind die Möglichkeiten? Warum würdest du das Skript laufen lassen und nicht ich? – kgrimes2

+3

Wie haben Sie Ihr Skript ausgeführt? Zeigen Sie genau, was Sie getan haben. Ich habe Ihren Code in eine Datei 'foo.sh' geschrieben, dann 'export VAL =" 6 "' und rannte 'bash foo.sh' und es hieß,' 6, ist eine Zahl'. Ich habe dann 'VAL =" ////// 6.000007 "' exportiert und rannte 'bash foo.sh' und sagte,' ///////6.000007, ist keine Zahl'. Sie können 'bash --version 'ausführen und angeben, welche Version von' bash 'Sie verwenden. – lurker

Antwort

0

Wie sich herausstellt, die Variablen, die ich mit meiner regex Vergleich hatte führende Zeilenumbrüche auf ihnen (zB "\n2.3333"), die abgezogen wurden mit echo. Wenn ich also die Werte mit echo auf dem Bildschirm anzeigen würde, würde ich die abgespeckte Version meiner Variablen sehen, die nicht mit der Regex verglichen wurde.

Lektion gelernt: echo ist nicht immer vertrauenswürdig. Per @ CharlesDuffy Kommentar nach einem der Verwendung zu sehen, was tatsächlich in Ihren Variablen ist: declare -p varname oder printf '%q\n' "$varname" aber tun nicht Verwendung echo $varname.

+0

Es ist viel einfacher, 'echo" $ var "' zu verwenden – wjandrea

1

Ihre Regex lässt keine Dezimalstellen im Exponenten zu. Exponenten können Dezimalzahlen haben, also müssen Sie entweder Ihre Definition ändern, was eine "Zahl" ist, oder Sie müssen Ihre Regex ändern.

Angenommen, die spätere, hier ist eine Korrektur (Bash 4.4):

echo "6.0 
1.22E3.7 
-2 
2.99999e-0.0001 
somestring///////6.0" >/tmp/f1.txt 

while IFS= read -r line || [[ -n $line ]]; do 
    if [[ "$line" =~ ^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[-+]?[0-9]*\.?[0-9]+)?$ ]] 
     then 
      echo $line, "is a number" 
     else 
      echo $line, "is not a number" 
    fi 
done < /tmp/f1.txt 

Drucke:

6.0, is a number 
1.22E3.7, is a number 
-2, is a number 
2.99999e-0.0001, is a number 
somestring///////6.0, is not a number 

ABER Sie sollten wissen, dass die meisten, die nur zwei legit Zahlen in Ihrer Liste betrachten 6.0 und -2 zu sein. Leichte Zugang zum Test ist mit awk:

$ awk '$1+0==$1{print $0 " is a number"; next} {print $0 " not a number"}' /tmp/f1.txt 
6.0 is a number 
1.22E3.7 not a number 
-2 is a number 
2.99999e-0.0001 not a number 
somestring///////6.0 not a number 

Der gleiche Sprache C-Funktion, dass awk eine Zeichenfolge mit einem Schwimmer zu konvertieren verwendet von vielen anderen Sprachen (Rubin, Perl, Python, C, C++, Swift verwendet wird, usw. usw.) Wenn Sie Ihr Format für gültig halten, werden Sie vermutlich auch Ihre eigene Konvertierungsroutine schreiben.

Zum Beispiel können Sie in den meisten Sprachen 10**1.5 als legitimes Float-Literal eingeben. Keine Sprache, die ich kenne, akzeptiert Dezimalzahlen nach dem e in einem String der Form 'xx.zzEyy.y'

+0

Ich entschuldige mich, diese "Zahlen", die ich in meinem Beitrag hatte, waren schlechte Beispiele aus dem Kopf und waren keine tatsächlichen Werte, die mit der Regex verglichen werden würden. Wie sich herausstellt, enthalten die Werte, die in '$ VAL' gespeichert wurden, etwas anderes als das, was auf dem Bildschirm gedruckt wurde, als ich 'echo $ VAL' auf ihnen lief. Also tat ich das: 'NEWVAR = $ (echo $ VAL)' und jetzt funktioniert es wie erwartet. Ich habe keine Ahnung warum, aber es tut es. – kgrimes2

+0

Ich würde erwarten, dass Ihr '$ VAL' führenden Whitespace enthält. 'echo $ VAL' word-splits und glob-expandiert den Inhalt Ihrer Variablen, anstatt diesen Inhalt unverändert auszugeben, sodass dieser Fehler maskiert wird. –

Verwandte Themen