Dans Bash, je peux écrire le test suivant
[[ "f" > "a" ]]
ce qui se traduit par un retour à 0, c'est-à-dire vrai. Comment bash effectue-t-il réellement cette comparaison de chaînes? De ma compréhension >
fait une comparaison entière. Essaie-t-il de comparer la valeur ASCII des opérandes?
De help test
:
STRING1 > STRING2
True if STRING1 sorts after STRING2 lexicographically.
En interne, bash utilise strcoll()
ou strcmp()
pour cela:
else if ((op[0] == '>' || op[0] == '<') && op[1] == '\0')
{
if (Shell_compatibility_level > 40 && flags & TEST_LOCALE)
return ((op[0] == '>') ? (strcoll (arg1, arg2) > 0) : (strcoll (arg1, arg2) < 0));
else
return ((op[0] == '>') ? (strcmp (arg1, arg2) > 0) : (strcmp (arg1, arg2) < 0));
}
Ce dernier compare en fait ASCII, le premier (utilisé lorsque les paramètres régionaux sont activés) effectue une comparaison plus spécifique qui convient au tri dans les paramètres régionaux donnés.
Il s'agit d'une comparaison alphabétique (AIUI, l'ordre de tri peut être influencé par les paramètres régionaux actuels). Il compare le premier caractère de chaque chaîne, et si celui de gauche a une valeur supérieure, c'est vrai, s'il est inférieur, il est faux; s'ils sont identiques, il compare le deuxième caractère, etc.
C'est pas identique à la comparaison d'entiers, pour cela vous utilisez [[ 2 -gt 1 ]]
ou (( 2 > 1 ))
. Pour illustrer la différence entre la comparaison de chaînes et d'entiers, considérez que tous les éléments suivants sont "vrais":
[[ 2 > 10 ]] # because "2" comes after "1" in ASCII sort order
[[ 10 -gt 2 ]] # because 10 is a larger number than 2
(( 10 > 2 )) # ditto
Voici quelques autres tests qui sont vrais en tant que comparaisons de chaînes, mais qui seraient faux avec une comparaison d'entiers:
[[ 05 < 5 ]] # Because "0" comes before "5"
[[ +5 < 0 ]] # Because "+" comes before the digits
[[ -0 < 0 ]] # Because "-" comes before the digits
[[ -1 < -2 ]] # Because "-" doesn't change how the second character is compared
Oui, il compare la valeur ascii et s'il est égal, répétez la comparaison avec le caractère suivant.
/* Copyright (C) 1991, 1996, 1997, 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <string.h>
#include <memcopy.h>
#undef strcmp
/* Compare S1 and S2, returning less than, equal to or
greater than zero if S1 is lexicographically less than,
equal to or greater than S2. */
int
strcmp (p1, p2)
const char *p1;
const char *p2;
{
register const unsigned char *s1 = (const unsigned char *) p1;
register const unsigned char *s2 = (const unsigned char *) p2;
unsigned reg_char c1, c2;
do
{
c1 = (unsigned char) *s1++;
c2 = (unsigned char) *s2++;
if (c1 == '\0')
return c1 - c2;
}
while (c1 == c2);
return c1 - c2;
}