]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
test: add string operators added by POSIX 2024
authorCollin Funk <collin.funk1@gmail.com>
Sat, 2 Nov 2024 03:49:16 +0000 (20:49 -0700)
committerPádraig Brady <P@draigBrady.com>
Sat, 2 Nov 2024 14:03:49 +0000 (14:03 +0000)
* src/test.c (binop): Recognize the ">" and "<" operators.
(three_arguments): Likewise.
(binary_operator): Implement the "<" and ">" operators.
(usage): Add operators to --help output.
* tests/test/test.pl (@Tests): Add functionality tests.
* doc/coreutils.texi (test invocation, String tests): Document new
operators.
* NEWS: Mention the new feature.

NEWS
doc/coreutils.texi
src/test.c
tests/test/test.pl

diff --git a/NEWS b/NEWS
index 75263d0272050930846d39df95822798be3acb5b..64d137ab0f8be93dd1888e4416d348b0a7e19150 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -46,6 +46,9 @@ GNU coreutils NEWS                                    -*- outline -*-
   %<i>$ format, where '<i>' is an integer referencing a particular argument,
   thus allowing repetition or reordering of printf arguments.
 
+  test supports the POSIX:2024 specified '<' and '>' operators with strings,
+  to compare the string locale collating order.
+
   timeout now supports the POSIX:2024 specified -f, and -p short options,
   corresponding to --foreground, and --preserve-status respectively.
 
index 60a07b2ef79ec61118660340b639a192ef7dd987..e016fdf26af63b3a99e3c2a42b1887b13fde49a1 100644 (file)
@@ -13733,7 +13733,7 @@ Exit status:
 * File type tests::             @code{-[bcdfhLpSt]}
 * Access permission tests::     @code{-[gkruwxOG]}
 * File characteristic tests::   @code{-e -s -nt -ot -ef}
-* String tests::                @code{-z -n = == !=}
+* String tests::                @code{-z -n = == != > <}
 * Numeric tests::               @code{-eq -ne -lt -le -gt -ge}
 * Connectives for test::        @code{! -a -o}
 @end menu
@@ -13942,6 +13942,16 @@ shells and systems.
 @cindex not-equal string check
 True if the strings are not equal.
 
+@item @var{string1} > @var{string2}
+@opindex >
+@cindex greater-than string check
+True if @var{string1} is greater than @var{string2} in the current locale.
+
+@item @var{string1} < @var{string2}
+@opindex <
+@cindex less-than string check
+True if @var{string1} is less than @var{string2} in the current locale.
+
 @end table
 
 
index 5af924347400091091a2854c70ff1cd1d8b69a96..7d3a78879231e4a8d5e4309ace3b81003afe1a9c 100644 (file)
@@ -173,7 +173,7 @@ static bool
 binop (char const *s)
 {
   return ((STREQ (s,   "=")) || (STREQ (s,  "!=")) || (STREQ (s, "==")) ||
-          (STREQ (s,   "-nt")) ||
+          (STREQ (s,   "-nt")) || (STREQ (s, ">")) || (STREQ (s, "<")) ||
           (STREQ (s, "-ot")) || (STREQ (s, "-ef")) || (STREQ (s, "-eq")) ||
           (STREQ (s, "-ne")) || (STREQ (s, "-lt")) || (STREQ (s, "-le")) ||
           (STREQ (s, "-gt")) || (STREQ (s, "-ge")));
@@ -189,7 +189,7 @@ binop (char const *s)
  *     '-t' int
  *     '-'('z'|'n') string
  *     string
- *     string ('!='|'=') string
+ *     string ('!='|'='|>|<) string
  *     <int> '-'(eq|ne|le|lt|ge|gt) <int>
  *     file '-'(nt|ot|ef) file
  *     '(' <expr> ')'
@@ -371,6 +371,20 @@ binary_operator (bool l_is_l)
       return value;
     }
 
+  if (STREQ (argv[op], ">"))
+    {
+      bool value = strcoll (argv[pos], argv[pos + 2]) > 0;
+      pos += 3;
+      return value;
+    }
+
+  if (STREQ (argv[op], "<"))
+    {
+      bool value = strcoll (argv[pos], argv[pos + 2]) < 0;
+      pos += 3;
+      return value;
+    }
+
   /* Not reached.  */
   affirm (false);
 }
@@ -615,7 +629,8 @@ three_arguments (void)
       value = one_argument ();
       advance (false);
     }
-  else if (STREQ (argv[pos + 1], "-a") || STREQ (argv[pos + 1], "-o"))
+  else if (STREQ (argv[pos + 1], "-a") || STREQ (argv[pos + 1], "-o")
+           || STREQ (argv[pos + 1], ">") || STREQ (argv[pos + 1], "<"))
     value = expr ();
   else
     test_syntax_error (_("%s: binary operator expected"),
@@ -708,6 +723,8 @@ EXPRESSION is true or false and sets exit status.  It is one of:\n\
   -z STRING            the length of STRING is zero\n\
   STRING1 = STRING2    the strings are equal\n\
   STRING1 != STRING2   the strings are not equal\n\
+  STRING1 > STRING2    STRING1 is greater than STRING2 in the current locale\n\
+  STRING1 < STRING2    STRING1 is less than STRING2 in the current locale\n\
 "), stdout);
       fputs (_("\
 \n\
index 0433461d86e044aebe93c65d31f0242bff3ce0e2..e8509448b4ada91ca0fd81e6b3620416a06456c0 100755 (executable)
@@ -185,6 +185,14 @@ my @Tests =
   ['paren-3', "'(' ')' ')'"],
   ['paren-4', "'(' ! ')'"],
   ['paren-5', "'(' -a ')'"],
+
+  ['less-collate-1', "'a' '<' 'b'"],
+  ['less-collate-2', "'a' '<' 'a'", {EXIT=>1}],
+  ['less-collate-3', "'b' '<' 'a'", {EXIT=>1}],
+
+  ['greater-collate-1', "'b' '>' 'a'"],
+  ['greater-collate-2', "'a' '>' 'a'", {EXIT=>1}],
+  ['greater-collate-3', "'a' '>' 'b'", {EXIT=>1}],
 );
 
 @Tests = add_inverse_op_tests \@Tests;