LINUX.ORG.RU
ФорумAdmin

Сравнение переменных в bash

 


0

3

Доброго времени суток всем. Пишу скриптик и что то не могу никак сообразить как сделать проверку переменной определенным образом... Собственно сама задача такова, есть переменная в которую попадают айпи адреса, адреса из разных сетей, допусти одни вида 172.16.*.*, другие 176.56.*.*, взависимости от того из какой сети адрес, те или иные инструкции далее... И вот я что то сильно затупил над тем как выполнить проверку переменной для той или иной подсети... Возможно ли вообще такое? Если да, то как лучше сделать?


есть два способа:

1. рассматривать IP как строку, и проверять например так:

if [ "$IP" != "${IP#172.16.*}" ]; then …
fi

2. IP это вообще-то целое число типа uint32_t, можно перевести IP в число, и сравнивать арифметически:

if (( IP >= IP_START && IP <= IP_END ))

но как их преобразовать я не знаю(в bash).

emulek
()
Ответ на: комментарий от emulek

Большое спасибо, первый вариант вполне подошел)

OxOyD
() автор топика
Ответ на: комментарий от Deleted

велосипед можно и на чистом баше навелосипедить

например

#!/bin/bash

declare -a ARRAY

IP=0

function ip_to_num
{
	OLD_IFS="$IFS"
	IFS="."
	ARRAY=( $1 )
	IP=0
	for (( J=0; J<4; J++))
	do
		(( IP *= 256 ))
		(( IP += ${ARRAY[$J]} ))
	done
	IFS="$OLD_IFS"
}

ip_to_num "192.168.0.0"
echo $IP
emulek
()
Ответ на: комментарий от emulek

нельзя. Нужна по любому expr(1), это уже не «чистый sh».

Ну здрасти, он тьюринг-полный. Парси и умножай-складывай самостоятельно. Не мужик что ли? :)

Deleted
()
Ответ на: комментарий от Deleted

Парси и умножай-складывай самостоятельно. Не мужик что ли?

это слишком просто. Вот sed — совсем другое дело.

emulek
()
Ответ на: комментарий от emulek

Нужна по любому expr(1), это уже не «чистый sh».

Почитал SuS3. Конструкция $(()) входит в стандарт.

ip_to_num()
{
	local old_IFS="$IFS"
	IFS="."
	local IP=0
	for d in $1; do
		IP=$(($IP * 256 + $d))
	done
	IFS="$old_IFS"
	echo $IP
}

ip_to_num 192.168.0.0
ip_to_num 255.255.255.255

Но стандарт требует числа бит, всего лишь, не ниже signed long, так что на 32-битных платформах можно обломиться.

Deleted
()
Ответ на: комментарий от emulek

Я упоролся и реализовал на sh сумматор чисел произвольной точности в обратной десятичной записи, не использующий конструкцию $(()) и не вызывающий внешних утилит. (За исключением echo для вывода результа.)

Сначала подготовим таблицу сложения десятичных цифр:

for i1 in 0 1 2 3 4 5 6 7 8 9 ; do
	for i2 in 0 1 2 3 4 5 6 7 8 9 ; do
		for i3 in 0 1 2 3 4 5 6 7 8 9 ; do
			echo sum3_d1_$i1$i2$i3=`expr $i1 + $i2 + $i3 | sed 's/^.\(.\)/\1/'`
			echo sum3_d2_$i1$i2$i3=`expr $i1 + $i2 + $i3 | sed 's/.$//'`
		done
	done
done > sum3table.sh

Теперь сам сумматор:

. ./sum3table.sh

is_empty() {
	return ${#1}
}

first_digit() {
	case "$1" in
	0*)
		r=0
	    ;;
	1*)
		r=1
	    ;;
	2*)
		r=2
	    ;;
	3*)
		r=3
	    ;;
	4*)
		r=4
	    ;;
	5*)
		r=5
	    ;;
	6*)
		r=6
	    ;;
	7*)
		r=7
	    ;;
	8*)
		r=8
	    ;;
	9*)
		r=9
	    ;;
	*)
		r='?'
	    ;;
	esac
	if is_empty "$1" ; then
		r=0
	fi
}

sum() {
	local result
	local s1="$1"
	local s2="$2"
	local s3=''
	local r1
	local r2
	while ! is_empty "$s1$s2$s3" ;  do
		first_digit "$s1" ;  d1=$r
		first_digit "$s2" ;  d2=$r
		first_digit "$s3" ;  s3=$r
		eval r1=\$sum3_d1_$d1$d2$s3
		eval s3=\$sum3_d2_$d1$d2$s3
		result="$result$r1"
		s1="${s1##$d1}"
		s2="${s2##$d2}"
	done
	r=$result
}

sum 1 6 ; echo $r
sum 01 6 ; echo $r
sum 72 3 ; echo $r
sum 8999 2 ; echo $r
sum 9998 2 ; echo $r
sum 9182 302000001 ; echo $r
Числа надо читать в обратную сторону, да. Справа налево.

Вот sed — совсем другое дело.

Милости просим, делай. :D

Deleted
()

Запиши 172.16.*.* это как regexp

IP='172.16.1.2'
REGEXP1='172\.16\..*\..*'

if echo "$IP" | grep -q "$REGEXP1"; then
...
fi

И никаких башизмов.

sdio ★★★★★
()

ipcalc, grepcidr

P.S. Куда катится ЛОР, прочитал весь тред, никто их не упомянул. Одни велосипеды.

Bers666 ★★★★★
()
Последнее исправление: Bers666 (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.