Как проверить строки на лексикографию, меньшую или равную в Bash?

В Bash, есть ли простой способ проверить, является ли одна строка лексикографически меньше или равна другой?

Я знаю, что вы можете сделать:

if [[ "a" < "b" ]]

для проверки строгого неравенства, или

if [[ 1 -le 1 ]]

для номеров. Но -le не похоже на работу со строками, а использование <= дает синтаксическую ошибку.

5 ответов

Решение

Просто отрицать больше, чем тест:

if [[ ! "a" > "b" ]]

Вам нужно использовать || with an additional condition instead of <=:

[[ "$a" < "$b" || "$a" == "$b" ]] 

sortPOSIX обходной путь

Не бесконечно устойчивы к строкам с символами новой строки, но когда это когда-либо происходит при работе со скриптами оболочки?

string_lte() (
  s="$(printf "${1}\n${2}")"
  if [ "$(printf "$s" | sort)" = "$s" ]; then
    exit 0
  else
    exit 1
  fi
)
string_lte abc adc || echo fail
string_lte adc adc || echo fail
string_lte afc adc && echo fail

Вы можете перевернуть сравнение, подписать и проверить отрицательно:

$ a="abc"
$ b="abc"
$ if ! [[ "$b" > "$a" ]] ; then  echo "a <= b" ; fi
a <= b

Если вы хотите упорядочить последовательность "A", затем "a", затем "B"... используйте:

shopt -s nocaseglob

Если вы можете использовать синтаксис Bash, посмотрите ответы @anubhava и @gordon-davisson. С синтаксисом POSIX у вас есть две опции (обратите внимание на необходимые обратные слеши!):

с использованием -o оператор (ИЛИ):

[ "$a" \< "$b" -o "$a" = "$b" ] && echo "'$a' LTE '$b'" || echo "'$a' GT '$b'"

или используя отрицание:

[ ! "$a" \> "$b" ] && echo "'$a' LTE '$b'" || echo "'$a' GT '$b'"

Я предпочитаю первый вариант, потому что imho он более читабелен.

Другие вопросы по тегам