• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

Vergleich von zwei Strings in Funktion

Rumak18

Member
Hallo,
ich habe eine Funktion, mit der ich eine Variable definiere und diese dann weiterführend vergleiche. Leider sagt mir die Linux BASH, dass die Ergebnisse nicht identisch sind. Heißt: Meine Variable "CHECK" ist gleich "1", obwohl ich "0" erwarte. Kann mir Jemand helfen?

Code:
CHECK_WEB_FUNC()
{
RESULT=$(curl -Is http://www.google.de | head -1)
CORRECT_RESULT="HTTP/1.1 200 OK"
if [[ "$RESULT" == "$CORRECT_RESULT" ]]
then CHECK=0
else CHECK=1
fi
}

[root@localhost~]# CHECK_WEB_FUNC
[root@localhost~]# echo $RESULT
HTTP/1.1 200 OK
[root@localhost~]#echo $CHECK
1
 
Das http Protokoll schliesst immer mit \r\n ab, Linux nicht.
Deshalb:
Code:
RESULT=$(curl -Is http://www.google.de | head -1)
RESULT="${RESULT:0:-1}"
hier der Vergleich

Nicht getestet

Gruß
Gräfin Klara
 

abgdf

Guru
:thumbs:

Ich hatte dann noch so einen Hackaround gebaut:
Code:
RESULT=$(echo $RESULT | perl -e '$/="\r\n";while(<>){chomp; print}');
aber Deins ist noch besser.
 

marce

Guru
http://tldp.org/LDP/abs/html/string-manipulation.html#SUBSTREXTR01
https://stackoverflow.com/questions/19858600/bash-accessing-last-x-characters-of-a-string
 
Rumak18 schrieb:
Hi,
hmmm... könntet ihr mir das hier erklären?
RESULT="${RESULT:0:-1}"

Ich habe oben geschrieben:
Das http Protokoll schliesst immer mit \r\n ab, Linux macht das nicht.
d.h.
RESULT="$(curl -Is http://www.google.de | head -1)"
Nun ist in "$RESULT" das letzte Zeichen ein '\r'. Deshalb
RESULT="${RESULT:0:-1}"
löscht dieses letzte byte '\r'. Damit entspricht es deinem Vergleich.

Du kannst auch einen Einzeiler schreiben, vielleicht ist der einfacher zu verstehen:
Beispiel:
Code:
[[ "$(curl -Is http://www.google.de | head -1)" == $'HTTP/1.1 200 OK\r' ]] && echo "Super, alles OK"
Sollte funktionieren

Gruß
Gräfin Klara
 
OP
R

Rumak18

Member
Perfekte Erläuterung. Vielen Dank dafür! Jetzt macht es "Achso" in meinem Kopf
.... Kommando zurück...doch nicht ganz.

Du schreibst :

Das http Protokoll schliesst immer mit \r\n ab, Linux macht das nicht.
d.h.
RESULT="$(curl -Is http://www.google.de | head -1)"
Nun ist in "$RESULT" das letzte Zeichen ein '\r'.
Warum ist bei $RESTULT an dieser Stelle das letzte Zeichen ein "\r" und nicht "\n" wie im ersten Satz beschrieben, da ja bei http ein "\r\n" vorliegt?
 
Du liest den string von curl mit /bin/bash
RESULT="$(curl -Is http://www.google.de | head -1)"
und für bash ist - NORMALERWEISE - das Ende des strings bzw. Ende einer Zeile ein '\n'.
Dieses '\n' steht in Wahrheit wohl in "$RESULT" drinnen, wird aber von bash nicht interpretiert.
Änderst du aber dieses Verhalten mit dem Setzen von IFS, dann kann das Ende durchaus ein "\r\n" sein oder schon bei '\r' beendet werden.
Probiere es aus mit
IFS=$'\r'
vor deinem string_vergleich.
Eigentlich sollte bash dann bei '\r' den string splitten bzw. beenden....möglicherweise. Ich bin keine Spezialistin für bash.
 

abgdf

Guru
Oder Du nutzt doch meine Perl-Zeile, dann weißt Du mit Sicherheit, was Du abschneidest. ;)

Das ist der Vorteil von Perl: Es mag umfangreicher sein als bash, aber es ist leichter zu kontrollieren.
bash ist 'ne alte Zicke. :D
 
A

Anonymous

Gast
Vorsicht mit IFS auf Bash-Ebene wenn du nicht ganz genau verstanden hast, was du damit tust, kannst du dir mehr Probleme in die Scripte reinholen als du damit lösen kannst.

Problem ist recht einfach zu verstehen wenn man sich die Zeichenketten mal genauer anschaut.

Code:
robi@ULTRA-01:~> RESULT=$(curl -Is http://www.google.de | head -1)
robi@ULTRA-01:~> CORRECT_RESULT="HTTP/1.1 200 OK"

robi@ULTRA-01:~> echo $RESULT | hexdump -C
00000000  48 54 54 50 2f 31 2e 31  20 32 30 30 20 4f 4b 0d  |HTTP/1.1 200 OK.|
00000010  0a
Zeichen 16 ist 0x0d; Zeichen 17 ist 0x0a |.|

Code:
robi@ULTRA-01:~> echo $CORRECT_RESULT | hexdump -C
00000000  48 54 54 50 2f 31 2e 31  20 32 30 30 20 4f 4b 0a  |HTTP/1.1 200 OK.|
00000010
Zeichen 16 ist 0x0a; Zeichen 17 gibt es nicht.


Der Unterschied ist also ganz klar wie oben schon erwähnt im Zeilenende (Zeilensprung) zu finden, der hier einmal im DOS/Mac Format und einmal im Unix-Format vorliegt.

entweder muss das "0x0d 0x0a" gegen "0x0a" getauscht werden oder das "0x0a" gegen "0x0d 0x0a" um die Strings richtig vergleichen zu können
Wobei man jedoch bedenken muss, das das 0x0a (das Ende der Zeile) schon nicht mehr Bestandteil des Strings ist und in der Variable auch nicht vorhanden ist.

Möglichkeiten gibt es ganz viele., hier mal ein paar in der Pipe geschrieben, hexdump am ende, damit man besser sieht was genau passiert.
Code:
Bash       :  (Beispiel schon oben genannt.)  ${RESULT:0:-1}                 (Bedeutet: Ausschnitt 1. bis Vorletztes Zeichen)
           :  echo ${RESULT%?}  | hexdump -C                               #letztes Zeichen wegschneiden
tr         :  echo $RESULT | tr -d "\r" | hexdump -C   
cut        :  echo $RESULT | cut -d $(echo -en "\r")  -f 1 | hexdump -C  
sed        :  echo $RESULT | sed 's/\r//g' | hexdump -C                     # 0x0d wird weggeschnitten
           :  echo $RESULT | sed 's/\(.*\)./\1/'| hexdump -C                  # letztes Zeichen wird weggeschnitten
awk        :  echo $RESULT | awk '{gsub(/\r/,"");print}' | hexdump -C
dos2unix   :  echo $RESULT | dos2unix | hexdump -C
......

Anderes herum geht das genauso, eben am Ende noch ein "\r" Anhängen oder unix2dos konvertieren.
Das macht sich auch ganz gut gleich bei der Erstellung der Variable zu erledigen. zB.
Code:
CORRECT_RESULT=$(echo -e "HTTP/1.1 200 OK\r")
Dann kann man sich im Scriptverlauf sparen die ganzen Ergebnisse jedesmal erst noch umwandeln zu müssen.

robi
 
OP
R

Rumak18

Member
Ok. Nun verstanden...mir war nicht klar, dass die BASH ein "Carriage Return" liefert. Ich dachte, die BASH liefert einen "Line Feed".
 
Oben