2016-11-21 5 views
2

Я получаю ошибки при использовании побитовых & операторов в/bin/sh. Я могу заставить его работать в bash, но скрипт, который будет запускать код, запускается в обычной оболочке, поэтому мне нужно заставить его работать в обычной регулярной оболочке. Мне нужно просто проверить, установлен ли определенный бит, например. 7-й битПобитовые операторы поддерживаются в обычной оболочке/bin/sh (не bash)

После кода работы в Баш, но не в/бен/ш

#!/bin/bash 
y=93 
if [ $((($y & 0x40) != 0)) ]; then 
    echo bit 7 is set 
fi 

Я попытался выше в/бен/ш путем удаления arithmatic расширения

#!/bin/sh 
y=93 
val=`expr $y & 0x40` 
if [ $val != 0 ]; then 
    echo worked 1 
fi 

Может кто-то подскажет, как побитовое оператор может использоваться в обычной регулярной оболочке?

+0

'sh' не поддерживает операции сдвига бит. – Inian

+0

NB: «бит 7» обычно считается MSB, например. с маской '0x80', с« бит 0 », являющейся LSB – Alnitak

+0

'/bin/sh' может быть либо POSIX sh (стандарт начала 1990-х годов), либо оболочкой Bourne (реализация эпохи 1970-х годов). В частности, в Solaris, оба из них присутствовали в наше время (с прежним обычно в '/ usr/xpg/bin', если последний находится в'/bin'); '$ (())' существует только в первом. Вы знаете, что у вас есть? –

ответ

2

Вы можете использовать деление и по модулю операций для проверки конкретного бита:

if [ `expr \($y/64 \) % 2` -eq 1 ]; then 
    echo bit 6 is set 
fi 
+0

'==' не гарантируется поддержкой POSIX sh в '[', и не поддерживается в пре-POSIX-реализациях '' '. Если вы пытаетесь быть совместимыми, используйте '=' (для сравнения строк) или '-eq' (для числового сравнения). –

+0

@CharlesDuffy да, у меня на самом деле нет старого non-bash/bin/sh для тестирования с – Alnitak

+0

@CharlesDuffy Я думаю, что теперь это должно работать на любой версии 'sh' – Alnitak

1

Я думаю, проблема в том, что вы используете строку, возвращаемую вашим арифметическим расширением, а не код выхода. Вы, вероятно, следует сделать тест на равное 0 на внешней стороне, как

if [ "$((y & 0x40))" -ne 0 ]; then 

иначе $(((y & 0x40) != 0)) возвращает строку, и она всегда будет не пусто, так испытание истина всегда будет проходить.

+1

POSIX указывает '&' в [набор арифметических операций, на которые ссылается ссылка в стандарте POSIX sh] (http://pubs.opengroup.org/onlinepubs/007904875/utilities/xcu_chap01.html#tag_01_07_02_01), поэтому, если OP работает с POSIX sh, а не с Bourne, это действительно должно работать. –

+0

...к сожалению, Solaris отправила оба в последние десятилетия, поэтому нам нужно уточнить из OP, на какой именно реализации они работают, чтобы точно знать, относится ли этот ответ. –

+0

(я почти * хотел сказать, что было бы безопаснее переключать константу из шестнадцатеричного в десятичный, но, внимательно изучая арифметический стандарт POSIX sh, нужны шестнадцатеричные константы для POSIX sh, поэтому мы действительно в хорошем месте здесь, если OP не использует Bourne). –

0

на основе Альнитак ответа, я бы:

if expr \($y/128 \) % 2 > /dev/null; then 
    echo bit 7 is set 
fi 

Это всего лишь немного более кратким.

Обратите внимание: 2^7 = 128