LinuxForum.Fans
Тема

Изучаю bash (не могу решить маленькую задачку)

Автор: aivs 22 сообщений 8536 просмотров
#167975

Изучаю bash программирование по Advanced Bash-Scripting Guide
Там есть задачка написать функцию 'isfloat ()', которая проверяла бы вещественные числа.
Есть подсказка: Эта функция подобна функции 'isdigit ()', надо лишь добавить анализ наличия десятичной точки.
Вот функция isdigit()

text

isdigit ()    # Проверка - состоит ли вся строка только из цифр.
{             # Другими словами - является ли строка целым числом.
  [ $# -eq 1 ] || return $FAILURE

case $1 in *[!0-9]*|"") return $FAILURE;; # не число *) return $SUCCESS;; esac }

Если проверяю вещественное число так: *[0-9]*"."*[0-9]* # число.число
То все отлично срабатыет
Если проверяю вещественно число и обычное число: *[0-9]*"."*[0-9]*|*[0-9]* # число.число или число
То тоже все отлично
Но мне по задумке скрипта нужно проверить:
Если это не число, то FAILURE(не число) инача SUCCESS (число)
Поствить НЕ перед проверкой на число просто *[!0-9]*

А как посавить НЕ перед этим набором *[0-9]*"."*[0-9]* ??????

#167989
aivs написал:
А как посавить НЕ перед этим набором *[0-9]*"."*[0-9]* ??????

зачем?

#168004


qq=6666
case $qq in
*[^0-9]* )
echo "1" # иные символы
;;
* ) echo "2" # Если там целое число , ставим ретурн или че тебе там надо
;;
esac

вроде так
а как там с *[0-9]*"."*[0-9]* не знаю

#168033

Вы меня не поняли, мне нужно проверить целое это число или дробное (2.3; 45.5) алгорит такой: если перед точкой и после точки цифра, значит это дробное число.
mogul82 Ваш варинт у меня в вопросе есть и он проверяет является ли символ целым числом, если ввести 5.5, то естественно он не поймет точку.
drBatty у mogul82 правильно прокомментировано, зачем отрицание.
Если вы мне предложите вариант без отрицания, буду только рад

#168083
aivs написал:
Если вы мне предложите вариант без отрицания, буду только рад

нету такого варианта в BASH (в синтаксисе case esac).

aivs написал:
*[0-9]*"."*[0-9]*

никакое это не число.

man bash написал:
Pathname Expansion
After word splitting, unless the -f option has been set, bash scans each word for the characters *, ?, and
[. If one of these characters appears, then the word is regarded as a pattern, and replaced with an
alphabetically sorted list of file names matching the pattern. If no matching file names are found, and
the shell option nullglob is not enabled, the word is left unchanged. If the nullglob option is set, and
no matches are found, the word is removed. If the failglob shell option is set, and no matches are found,
an error message is printed and the command is not executed. If the shell option nocaseglob is enabled,
the match is performed without regard to the case of alphabetic characters. When a pattern is used for
pathname expansion, the character ``.'' at the start of a name or immediately following a slash must be
matched explicitly, unless the shell option dotglob is set. When matching a pathname, the slash character
must always be matched explicitly. In other cases, the ``.'' character is not treated specially. See
the description of shopt below under SHELL BUILTIN COMMANDS for a description of the nocaseglob, nullglob,
failglob, and dotglob shell options.

это
- любые символы
- цифра(ОДНА!)
- любые символы
- точка
- любые символы
- цифра(ОДНА!)
- любые символы

mogul82, зачем пишете-то?
по вашему (проверьте) 6.66 это "иные символы".
ваш шаблон читается как
- любое число любых символов
- одна нецифра
- любое число любых символов
Зачем это ТС - решительно непонятно.

ЗЫЖ проверить можно так: откусить цифру в цикле. Например, если строка S=12345, то ${S%[0-9]} = 1234
но вот "много цифр" в Pathname Expansion нету.

ЗЗЫЖ используйте regex и не занимайтесь ерундой.

#168084

[console]ksu@ksu:~/test$ bash mg.sh 1
1 число
ksu@ksu:~/test$ bash mg.sh 12
12 число
ksu@ksu:~/test$ bash mg.sh 123
123 число
ksu@ksu:~/test$ bash mg.sh 1234
1234 не число
ksu@ksu:~/test$ bash mg.sh X
X не число
ksu@ksu:~/test$ cat mg.sh
qq=$1
case $qq in
[0-9])
;&
[0-9][0-9])
;&
[0-9][0-9][0-9])
echo $qq число
;;
*)
echo $qq не число
esac
[/console]

#168087
emulek написал:
по вашему (проверьте) 6.66 это "иные символы".
ваш шаблон читается как
- любое число любых символов
- одна нецифра
- любое число любых символов

мой шаблон читается так:
только цифры и ни каких других символов в.т.ч. точки и буквы

и
7.77
4435.43534534
фывфывф
й

не входят
только ели числа то echo "2"
все остальное echo "1"

#168094
text

isdigit ()    # Проверка - состоит ли вся строка только из цифр.
{             # Другими словами - является ли строка целым числом.
  [ $# -eq 1 ] || return $FAILURE

case $1 in [0-9]*\.[0-9]*) return $SUCCESS;; *) return $FAILURE;; # не флоат esac }

не?

#168100
text
case $1 in
    *[!0.0-9.0]*|"") echo "Строка не цифра";;
              *) echo "Строка из цифр" ;;
esac

Вот так!, теперь в диапазон проверки входят и целые и дробные числа.

#168128
mogul82 написал:
мой шаблон читается так:
только цифры и ни каких других символов в.т.ч. точки и буквы

facepalm...
это код так работает - вы отлавливаете хотя-бы одну нецифру, и если нецифр нет, выполняется вторая часть case'а.

voral написал:
не?

нет. вы написали бред.

Показать
ksu@ksu:~/test$ bash voral.sh 12
64
ksu@ksu:~/test$ bash voral.sh aa
64
ksu@ksu:~/test$ bash voral.sh 1
64
ksu@ksu:~/test$ bash voral.sh 1.1
0
ksu@ksu:~/test$ bash voral.sh 1.1a
0
ksu@ksu:~/test$ bash voral.sh 1sss.1a
0
ksu@ksu:~/test$ bash voral.sh aa
64
ksu@ksu:~/test$ bash voral.sh 17
64
ksu@ksu:~/test$ cat voral.sh
FAILURE=64
SUCCESS=0

isdigit () # Проверка - состоит ли вся строка только из цифр.
{ # Другими словами - является ли строка целым числом.
[ $# -eq 1 ] || return $FAILURE

case $1 in
[0-9]*\.[0-9]*) return $SUCCESS;;
*) return $FAILURE;; # не флоат
esac
}
isdigit "$1"
echo $?

почему "бред"? потому что вы не только меня не слушаете, но и документацию читать не желаете.
[0-9]*\.[0-9]*
означает
- цифра
- любые символы
- точка
- цифра
- любые символы

aivs написал:
Вот так!, теперь в диапазон проверки входят и целые и дробные числа.

ну а это и комментировать не буду.

#168179

voral, в bash'е в кейсе не регэкспы, а что-то вроде маски... с регэкспами работается так:

text
 
FLOAT_REG='^[0-9]*\.[0-9]*$'
if [[ $1 =~ $FLOAT_REG ]] ; then
    echo SUCCESS;
else
    echo FAILURE;
fi

сюда ещё несложно всяких плюшек добавить типа знаков, экспоненты итп...

aivs написал:
Вот так!, теперь в диапазон проверки входят и целые и дробные числа.

это просто произвольная строка из точек и цифр, например "1.2..3...4...5" итп..

#168185
Fat-Zer написал:
voral, в bash'е в кейсе не регэкспы, а что-то вроде маски... с регэкспами работается так:

ok. запомнил. спасибо :)

#168196

это просто произвольная строка из точек и цифр, например "1.2..3...4...5" итп..
Да действительно.
Так как мне в case сделать проверку целое число введено или дробное, попробовал все предложенные варианты, ни один не работает.
#168203
aivs написал:
Так как мне в case сделать проверку целое число введено или дробное, попробовал все предложенные варианты, ни один не работает.

а почему такое желание кейсом сделать?

#168226

Изучаю bash по Advanced Bash-Scripting Guide
http://rus-linux.net/MyLDP/BOOKS/abs-guide/flat/abs-book.html
Прочитал главу 10.4. Операторы выбора

"Пример 10-28. Проверка ввода"

text
isdigit ()    # Проверка - состоит ли вся строка только из цифр.
{             # Другими словами - является ли строка целым числом.
  [ $# -eq 1 ] || return $FAILURE

case $1 in *[!0-9]*|"") return $FAILURE;; *) return $SUCCESS;; esac }

После пример идет упражнение на закрепление материала:

# Упражнение:
# --------
# Напишите функцию 'isfloat ()', которая проверяла бы вещественные числа.
# Подсказка: Эта функция подобна функции 'isdigit ()',
#+ надо лишь добавить анализ наличия десятичной точки.


надо лишь добавить анализ наличия десятичной точки подразумевает, что это сделать легко

Я просто хочу закрепить полученный материал

#168915
aivs написал:
надо лишь добавить анализ наличия десятичной точки подразумевает, что это сделать легко
Я просто хочу закрепить полученный материал

а...

смотрите: вам надо найти либо число, вы уже знаете как это делать

text
*[^0-9]*) # есть хоть одна нецифра. не то(раньше)
;;

*) # нецифр нет. число без точки ;;

вот в первом выборе надо не плакать "не число", а продолжить анализ. (т.е. заменить ;; на ;&)

вам надо проверить,

text
*[^0-9.]*) # есть хоть один символ не цифра и не точка. не то
;;

# вот тут вроде то, только цифры и точки. например 3.14, проблема, что ...7...5...55... это тоже "число"

*.*.*) # о как - по-русски: если есть две точки (или больше). Не то ;;

*) # нашли! дробное число вида цифры_точка_цифры!

#170621

Огромное спасибо, всего лишь надо было продолжить анализ!!

#173276

Подскажите еще с одним вопросом, мне нужно проверить строку с цифрами и знаком %.

Алгоритм такой:
Если введена строка [цифры]% # например 15%
то преобразовать ее к виду [только цифры]

Не знаю как сравнить строку с шаблоном [цифры]%

Вижу это как то так:

case $stroka in
[0-9] ) echo "цифра"
[0-9]% ) echo " цифра и проценты"; stroka=$(echo $stroka | tr -d %)
esac

Знаю что вот так не правльно [0-9]% , подскажите как правильно??

#173346

если с помощью case, то тоже самое, что и с точкой:

text

case $stroka in
    *[^0-9%]* ) echo "не то" #отсекаем если есть что-то кроме цифр и процентов
    *%*%*) echo "не то" # отсекаем если есть два процента
    *%) echo "наш случай" # процент должен быть в конце
    *) echo "не то"
esac
#173780

Спасибо, а если через if, или какой вариант более правильный?

Войдите или зарегистрируйтесь, чтобы ответить.