Проверить, содержит ли переменная более 4 цифр в скрипте bash

Более полезная удаленная команда, основанная на ответе @thrig:

Host someHost
Hostname 1.2.3.4
LocalForward 15673 localhost:15672
RequestTTY no
RemoteCommand bash -c 'echo "Listening on port 15673"; read -r -d '' _'

read -r -d '' _будет блокировать соединение, пока пользователь не нажмет control+c.

0
05.04.2021, 18:58
4 ответа

Если вы хотите проверить количество символов в переменной, вы можете сделать это...

var="foo bar"
echo "var contains ${#var} characters"

Result:
var contains 7 characters
1
28.04.2021, 22:54

Я бы сделал

#!/usr/bin/env bash

die () { echo "$*" >&2; exit 1; }

input=$1
[[ $input == +([[:digit:]]) ]] || die "only digits please"
(( input <= 9999 ))            || die "no more than 4 digits please"
echo "ok: $input"
3
28.04.2021, 22:54

Если вас интересует количество цифр (, а не числовое значение ), вы можете сопоставить регулярное выражение в Bash/Ksh/Zsh (*, см. сноску к[[:digit:]]):

#!/bin/bash
input=$1
re='^[[:digit:]]{1,4}$'
if [[ $input =~ $re ]]; then
    echo "'$input' contains 1 to 4 digits (and nothing else)"
else
    echo "'$input' contains something else"
fi

Или, например,. [[ $input =~ ^[[:digit:]]{5,}$ ]]для проверки «5 или более цифр (и ничего больше )» и т. д.


Или в чистой оболочке POSIX, где вы должны использовать caseдля сопоставления с образцом:

#!/bin/sh
input=$1
case $input in 
    *[![:digit:]]*) onlydigits=0;; # contains non-digits
    *[[:digit:]]*)  onlydigits=1;; # at least one digit
    *)              onlydigits=0;; # empty
esac

if [ $onlydigits = 0 ]; then
    echo "'$input' is empty or contains something other than digits"
elif [ "${#input}" -le 4 ]; then
    echo "'$input' contains 1 to 4 digits (and nothing else)"
else
    echo "'$input' contains 5 or more digits (but nothing else)"
fi

(Вы могли бы поместить всю логику в case, но вложение ifтам несколько уродливо, ИМО.)


Обратите внимание, что [[:digit:]]должно соответствовать любому представлению о «цифрах» в текущей локали. Это может быть или не быть больше, чем цифры ASCII 0123456789. В моей системе [[:digit:]]не соответствует, например. ⁴ (верхний индекс четыре, U+2074 ), но [0-9]есть. Сопоставление других «цифр» может быть проблемой, особенно. если вы делаете арифметику на число в оболочке. Итак, если вы хотите быть более строгим, используйте [0123456789], чтобы принимать только цифры ASCII.

3
28.04.2021, 22:54

Здесь предполагается, что вы имеете в виду только десятичные цифры ASCII, а не другие виды десятичных или не-десятичных цифр.

shopt -s extglob # enables a subset of ksh extended globs including *(...),
                 # +(...) and ?(...) but unfortunately not {4}(...)

d='[0123456789]' nd='[^0123456789]'

case $input in
  ( $d$d$d$d+($d)     ) echo made of more than 4 digits;;
  ( *$d*$d*$d*$d*$d*  ) echo contains more than 4 digits;;
  ( ""                ) echo empty;;
  ( *($nd)            ) echo does not contain any digit;;
  ( *$nd*             ) echo no more than 4 digits but also contains non-digits;;
  ( $d?($d)?($d)?($d) ) echo made of 1 to 4 digits;;
  ( *                 ) echo should not be reached;;
esac

Имейте в виду, что в bashи в зависимости от системы и локали [0-9]и [[:digit:]]могут совпадать не только с 0123456789, поэтому их не следует использовать для проверки ввода (, подробнее об этом в . ] этот ответ на другой вопрос здесь например ).

Также имейте в виду, чтоbashсопоставление с образцом работает очень -неожиданным образом в многобайтовых -локалях .

Вы обнаружите, что, например, в zh_CN.gb18030китайской локали на input='1-©©'он вернет no more than 4 digits but also contains non-digits, как и ожидалось, но если вы добавите один 0x80байт (input='1-©©'$'\x80'), он вернет contains more than 4 digits. ].

Именно по этой причине (и тому факту, что сопоставление с образцом, как известно, имеет ошибки в крайних случаях во многих оболочках ), для проверки ввода лучше использовать положительное сопоставление, где это возможно для вещей. вы принимаете (, а не отрицательное совпадение для вещей, которые нужно отклонить )¹, следовательно, $d?($d)?($d)?($d)выше, хотя это не должно быть необходимо, как, по крайней мере, теоретически, все остальное должно было сопоставляться более ранними шаблонами.


¹ в качестве исключения, возможно, потребуется рассмотреть неправильную функцию оболочки Bourne и Korn, из-за которой case $input in [x]) echo yes; esacсовпадает с x, а также с [x]!

5
28.04.2021, 22:54

Теги

Похожие вопросы