diff --git a/SC3012.md b/SC3012.md index fe1e8b8..0d85c78 100644 --- a/SC3012.md +++ b/SC3012.md @@ -1,4 +1,4 @@ -## In POSIX sh, lexicographical \< is undefined. +## In POSIX sh, lexicographical `\<` is undefined. ### Problematic code: @@ -16,25 +16,23 @@ fi First, make sure you wanted a lexicographical comparison (aka dictionary order), and not a numerical comparison. -The easiest fix is to switch to a shell that *does* support lexicographical comparison with `>`/`\>`, such as `bash`, `dash`, or `ksh`. Otherwise, you can use `awk` to compare lexicographically by making sure the strings contain at least some non-numerical data: +Then to compare as string, you can use `expr` and make sure that the strings are not interpreted numerically by adding some non-numerical data to them. Here, an apostrophe is prepended: ``` #!/bin/sh x="aardvark" y="zebra" -if awk -v first="'$x'" -v second="'$y'" 'BEGIN { exit (first < second) ? 0 : 1 }' +if expr "'$x" \< "'$y" > /dev/null then echo "$x comes before $y in the dictionary" fi ``` -The extra quotes in the awk `-v` flag are there to add non-numerical data to the string, otherwise `10 < 2` is treated as a numerical comparison (being false) instead of a lexicographical string comparison (being true). Any other non-numerical data can be used instead, such as `-v x="FOO$x"`. - ### Rationale: The `test` binary operators `>`, `\>`, `<`, and `\<` are not part of POSIX and not guaranteed to be supported in scripts targeting `sh`. -The `awk` functionality is POSIX and can safely be relied on. +The `expr` functionality is specified by POSIX. ### Exceptions: @@ -42,4 +40,4 @@ If you know your `sh` will be e.g. `dash`, consider explicitly using `#!/bin/das ### Related resources: -https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html#tag_20_128 +* POSIX: [test](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html#tag_20_128), [expr](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/expr.html)