BASH (вопросы и ответы.)

На самом деле это единственный раздел про unix на этом форуме

Модераторы: /dev/random, Модераторы разделов

Аватара пользователя
Naruto-kun
Сообщения: 228
Статус: небритый гентушник
ОС: Gentoo(PC)/easypeasy(Netbook)

BASH

Сообщение Naruto-kun »

В процессе написания скрипта у меня всё больше и больше увеличивается число используемых массивов, которые между собой тесно связаны. В связи с этим задался вопросом, а есть ли возможность реализации структур в баше, как на сях, например? Или что-то похожее по свойствам.
Bash - массивы и структуры
Сравнение чисел при помощи echo и bc (ver1)
Сравнение чисел при помощи echo и bc (ver2)
Сравнение чисел при помощи echo и bc (ver3)
Арифметические операции при помощи echo и bc
Арифметические операции при помощи echo и awk
Как из Шестнадцатиричного числа получить символ ASCII
Компьютер позволяет решать все те проблемы, которые до изобретения компьютера не существовали.
Если на вопрос ни кто не знает ответа, то пора читать описание.
Спасибо сказали:
Аватара пользователя
serzh-z
Бывший модератор
Сообщения: 8259
Статус: Маньяк
ОС: Arch, Fedora, Ubuntu

Re: BASH

Сообщение serzh-z »

Naruto-kun писал(а):
04.05.2009 17:47
есть ли возможность реализации структур в баше, как на сях, например? Или что-то похожее по свойствам.
Нет.
Спасибо сказали:
Аватара пользователя
serzh-z
Бывший модератор
Сообщения: 8259
Статус: Маньяк
ОС: Arch, Fedora, Ubuntu

Re: BASH

Сообщение serzh-z »

Аналогичный, кстати, вопрос: http://www.experts-exchange.com/Programmin...Q_20890007.html - разумеется это подобие "структуры" применимо к любому языку, поскольку со стороны языка ничего не требуется.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: BASH

Сообщение drBatty »

Naruto-kun писал(а):
04.05.2009 17:47
В процессе написания скрипта у меня всё больше и больше увеличивается число используемых массивов, которые между собой тесно связаны.

ИМХО надо другой язык использовать в таком случае...
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Naruto-kun
Сообщения: 228
Статус: небритый гентушник
ОС: Gentoo(PC)/easypeasy(Netbook)

Re: BASH

Сообщение Naruto-kun »

drBatty писал(а):
04.05.2009 18:05
Naruto-kun писал(а):
04.05.2009 17:47
В процессе написания скрипта у меня всё больше и больше увеличивается число используемых массивов, которые между собой тесно связаны.

ИМХО надо другой язык использовать в таком случае...


По некоторым причинам не могу, потому и задал этот вопрос. Если бы можно было использовать другой язык, тему бы не создавал.
UP Нашёл выход из положения без использования структур. Но вопрос всё равно оставлю, но уже для себя интересно.
Компьютер позволяет решать все те проблемы, которые до изобретения компьютера не существовали.
Если на вопрос ни кто не знает ответа, то пора читать описание.
Спасибо сказали:
Аватара пользователя
Portnov
Модератор
Сообщения: 1786
Статус: Матёрый линуксоид
ОС: Debian testing/unstable

Re: BASH

Сообщение Portnov »

Нуу... тиаретиццки... :)
В баше есть массивы. При достаточно большом желании их можно использовать как структуры:

Код: Выделить всё

X=0
Y=1
Z=2

POINT[$X]=5
POINT[$Y]=10
POINT[$Z]=15
echo ${POINT[$X]}, ${POINT[$Y]}, ${POINT[$Z]}
Работа: Ubuntu 9.10
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
Спасибо сказали:
Аватара пользователя
Naruto-kun
Сообщения: 228
Статус: небритый гентушник
ОС: Gentoo(PC)/easypeasy(Netbook)

Re: BASH

Сообщение Naruto-kun »

Ясно. Просто, по поводу массивов я знаю и во всю их использую, а вот как со структурами быть, не знал.

Возник ещё один вопрос, новую тему создавать не стал. Задам здесь же. Есть ли в баше возможность работать с данными типа float или double?
Просто у меня есть массив чисел типа: 11,2; 1,45; 1094,42; и тд. В скрипте мне их нужно сравнивать (что больше, что меньше). И исходя из условий вычитать одно из другого. Я пробовал так:

Код: Выделить всё

a[0]=1
a[1]=1,2
if [ ${a[1]} -gt {a[0]} ]; then
   let "a[1] = ((a[1]-a[0]))"
fi

На что он конечно ругался:

Код: Выделить всё

./test.sh: line 10: [: 1,2: integer expression expected
Компьютер позволяет решать все те проблемы, которые до изобретения компьютера не существовали.
Если на вопрос ни кто не знает ответа, то пора читать описание.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: BASH

Сообщение drBatty »

Naruto-kun писал(а):
05.05.2009 16:57
Просто у меня например есть массив чисел типа: 11,2; 1,45; 1094,42; и тд. В скрипте мне их нужно сравнивать
есть bc

Код: Выделить всё

drb ~$ echo "5<6" | bc
1
drb ~$ echo "100>256" | bc
0

с дробными числами он тоже может.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Naruto-kun
Сообщения: 228
Статус: небритый гентушник
ОС: Gentoo(PC)/easypeasy(Netbook)

Re: BASH

Сообщение Naruto-kun »

Попробовал, то что вы посоветовали. Выдал ошибку.

Код: Выделить всё

syntax error on line 1, teletype

К тому же вы указали, только пример сравнения. А как быть с арифметическими операциями вроде сложения или вычитания?
Компьютер позволяет решать все те проблемы, которые до изобретения компьютера не существовали.
Если на вопрос ни кто не знает ответа, то пора читать описание.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: BASH

Сообщение drBatty »

Naruto-kun писал(а):
05.05.2009 17:21
ак быть с арифметическими операциями вроде сложения или вычитания?

Код: Выделить всё

echo "2+2*2" | bc
6

есть в конце концов man bc!
ЗЫЖ как можно запускать непонятные команды?! может я вам знаменитый однострок на перле сую!

ЗЗЫЖ кстати возможности bc этим не исчерпываются, там есть функции(свои и стандартные, вроде синусов), переменные, разная степень точности, выбор системы счисления(хоть 13иричная!) и прочее. Незаменимая команда для работы с числами.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Naruto-kun
Сообщения: 228
Статус: небритый гентушник
ОС: Gentoo(PC)/easypeasy(Netbook)

Re: BASH

Сообщение Naruto-kun »

Ну судя по содержимому строки не очень похоже на знаменитый однострок на пёрле. C манами и хелпами же на работе - проблема. На работе не полноценный линух, а что-то вроде эмулятора терминала в винде. Не знаю почему, но манов тут и в помине нет. И собственно поэтому же я не боюсь никаких однострок, в крайнем случае эмулятор всегда могу ребутнуть, либо в само крайнем случае пересобрать. Приду домой почитаю на домашней тачке маны по bc.
PS. По поводу ошибки я так пока и не понял, в чём косяк. И что удиветильно ругается именно на операции сравнения, на арифметические операции не ругается.
Компьютер позволяет решать все те проблемы, которые до изобретения компьютера не существовали.
Если на вопрос ни кто не знает ответа, то пора читать описание.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: BASH

Сообщение drBatty »

Naruto-kun писал(а):
05.05.2009 17:36
И что удиветильно ругается именно на операции сравнения, на арифметические операции не ругается.
может bc тоже какой-то не полноценный. а если "5 < 2 * 2" ?
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Denjs
Сообщения: 1685
ОС: SuSe 10.2

Re: BASH

Сообщение Denjs »

ээээ.... можно попиариться? вам баш нужен или сойдет другой скриптовый язык?
QDroid - Среда исполнения и фреймворк для QtScript.
OTPD - Открытые драйвера промышленных принтеров чеков и этикеток (кроссплатформенная подсистема печати).
Спасибо сказали:
Аватара пользователя
Naruto-kun
Сообщения: 228
Статус: небритый гентушник
ОС: Gentoo(PC)/easypeasy(Netbook)

Re: BASH

Сообщение Naruto-kun »

drBatty писал(а):
05.05.2009 17:41
Naruto-kun писал(а):
05.05.2009 17:36
И что удиветильно ругается именно на операции сравнения, на арифметические операции не ругается.
может bc тоже какой-то не полноценный. а если "5 < 2 * 2" ?

Всё равно ошибку выдаёт.
Denjs писал(а):
05.05.2009 17:42
ээээ.... можно попиариться? вам баш нужен или сойдет другой скриптовый язык?

Именно баш.
Компьютер позволяет решать все те проблемы, которые до изобретения компьютера не существовали.
Если на вопрос ни кто не знает ответа, то пора читать описание.
Спасибо сказали:
Аватара пользователя
Denjs
Сообщения: 1685
ОС: SuSe 10.2

Re: BASH

Сообщение Denjs »

>>Именно баш.
да?.. но...
>>В процессе написания скрипта у меня всё больше и больше увеличивается число используемых массивов

Сдается мне вы ошиблись с выбором средства реализации...
QDroid - Среда исполнения и фреймворк для QtScript.
OTPD - Открытые драйвера промышленных принтеров чеков и этикеток (кроссплатформенная подсистема печати).
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: BASH

Сообщение drBatty »

Naruto-kun писал(а):
05.05.2009 17:48
Всё равно ошибку выдаёт.

дык попробуйте вычитание, и отрежьте первый символ, если "-" то первое число меньше второго. Проверять на равенство float ни в коем случае нельзя! Это как i++ + ++i в сях - руки кодерам отрывать за такое надо...
Denjs писал(а):
05.05.2009 19:29
Сдается мне вы ошиблись с выбором средства реализации...
я уже говорил, но почему-то надо... выше пост про это...
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Naruto-kun
Сообщения: 228
Статус: небритый гентушник
ОС: Gentoo(PC)/easypeasy(Netbook)

Re: BASH

Сообщение Naruto-kun »

дык попробуйте вычитание, и отрежьте первый символ, если "-" то первое число меньше второго. Проверять на равенство float ни в коем случае нельзя! Это как i++ + ++i в сях - руки кодерам отрывать за такое надо...

Хмм, попробую. Других идей у меня пока всё равно не появилось.
PS. Протестил bc дома, работает как часы. В очередной раз убедился в ущербности эмулятора у себя на работе.
Компьютер позволяет решать все те проблемы, которые до изобретения компьютера не существовали.
Если на вопрос ни кто не знает ответа, то пора читать описание.
Спасибо сказали:
Аватара пользователя
Naruto-kun
Сообщения: 228
Статус: небритый гентушник
ОС: Gentoo(PC)/easypeasy(Netbook)

Re: BASH

Сообщение Naruto-kun »

Нашёл выход из положения:

Код: Выделить всё

x=2.4
y=1.2
echo "$x $y" | awk '{if ($1 >= $2) print 1; else print 0}'
echo "$x $y" | awk '{print $1 + $2}'

В результате выдаёт, то что нужно:


PS. Всем, кто так или иначе помог, спасибо.
Компьютер позволяет решать все те проблемы, которые до изобретения компьютера не существовали.
Если на вопрос ни кто не знает ответа, то пора читать описание.
Спасибо сказали:
Аватара пользователя
Naruto-kun
Сообщения: 228
Статус: небритый гентушник
ОС: Gentoo(PC)/easypeasy(Netbook)

Re: BASH

Сообщение Naruto-kun »

Хмм, возник ещё один вопрос. Есть скрипт. В нём, в начале из файла все данные загоняются в массивы. У меня это сделано так:

Код: Выделить всё

i=0; while read line
do
    ddate[$i]=`echo $line | cut -d" " -f1`
    type[$i]=`echo $line | cut -d" " -f2`
    id[$i]=`echo $line | cut -d" " -f3`
    name[$i]=`echo $line | cut -d" " -f4`
    oper[$i]=`echo $line | cut -d" " -f5`
    let "i+=1"
done < ${LST}

Сделано так, потому что в файле между данными в строке разное число пробелов, а echo же насколько я понял и проверил на практике сводит всё к одному пробелу между данными. Хотелось бы узнать можно ли как то этот процесс ускорить. Может это возможно сделать быстрее?
PS. В данный момент файлы могут состоять из 1000 и более строк и процесс перегонки данных из файла в массивы занимает очень много времени.
Компьютер позволяет решать все те проблемы, которые до изобретения компьютера не существовали.
Если на вопрос ни кто не знает ответа, то пора читать описание.
Спасибо сказали:
Аватара пользователя
diesel
Бывший модератор
Сообщения: 5989
ОС: OS X, openSuSE, ROSA, Debian

Re: BASH

Сообщение diesel »

Код: Выделить всё

while read ddate[$i] type[$i] id[$i] name[$i] oper[$i]; do ...


не покатит? если нет ....

Код: Выделить всё

while read a b c d e; do
     ddate[$i] = a
     .....
Спасибо сказали:
Аватара пользователя
Naruto-kun
Сообщения: 228
Статус: небритый гентушник
ОС: Gentoo(PC)/easypeasy(Netbook)

Re: BASH

Сообщение Naruto-kun »

Спасибо за

Код: Выделить всё

while read ddate[$i] type[$i] id[$i] name[$i] oper[$i]; do ...

Оказалось в разы быстрее моего варианта. Спасибо большое.
PS. Раз уже так оказалось, может и здесь тогда подскажете как повысить скорость работы. Здесь основной алгоритм в следующем:
1) Сравниваем текущий счёт и предыдущий. (Начинаем это делать со 2-ого элемента)
2) Если счета окажутся одни и те же записываем сумму предыдущего счёта в счёт текущего.(Начинаем это делать со 2-ого элемента)
3) Проверяем больше или равно ли на счёту, чем сумма комиссии. (с помощью echo и awk, так как bc на работе у меня урезанный какой-то)
4) Если результат сравнения = 1 (В данном случае это будет означать, что средств достаточно), то:
4.1) Вычитаем из суммы счёта сумму комиссии, перед этим заменив в суммах запятые на точки ( У меня связка echo и awk в операции вычетания с запятыми почему то не не хочет работать).
4.2) Записываем изменённую сумму и заменяем обратно точку на запятую.
4.3) Выставляем право на съём = 1.
5) Если результат сравнения = 0, то выставляем право на съём = 0.
У меня реализовано так:

Код: Выделить всё

...
n=$i; i=0; # n - количество элементов.
while [ $i -lt $n ]
do
    if [ $i -gt 0 ]; then
        let "j = ((i-1))"
            if [ ${panCount[$i]} -eq ${panCount[$j]} ]; then
            panSum810[$i]=${panSum810[$j]}
        fi
    fi

    check=`echo "${panSum810[$i]} ${KomissSum810[$i]}" | awk '{if ($1 >= $2) print 1; else print 0}'`

    if [ $check -eq 1 ]; then
        panSum810_float=`echo ${panSum810[$i]} | sed -e 's/,/./'`
        komissSum810_float=`echo ${KomissSum810[$i]} | sed -e 's/,/./'`
        panSum810_float=`echo "$panSum810_float $komissSum810_float" | awk '{print $1 - $2}'`
        panSum810[$i]=`echo $panSum810_float | sed -e 's/\./,/'`
        operation_rull[i]=1
    elif [ $check -ne 1 ]; then
        operation_rull[i]=0
    fi
    let "i+=1"
done
...
Компьютер позволяет решать все те проблемы, которые до изобретения компьютера не существовали.
Если на вопрос ни кто не знает ответа, то пора читать описание.
Спасибо сказали:
Аватара пользователя
sash-kan
Администратор
Сообщения: 13939
Статус: oel ngati kameie
ОС: GNU

Re: BASH

Сообщение sash-kan »

Naruto-kun писал(а):
14.05.2009 15:41
между данными в строке разное число пробелов
не понятно. т.е. в строке могут быть пропущенные поля?
ну, перед парсингом вставьте между двумя подряд идущими пробелами что-нибудь, что вам не помешает. например, «""»:
sed 's/ / "" /g'
в любом случае, будет быстрее читать одной встроенной командой read, нежели запуском пяти процессов echo и пяти процессов cut.

p.s. пока писал, вышло, что писал напрасно. оказывается, никаких скрытых смыслов и не было. вот так всегда… не обращаешь внимания на ник.
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
Спасибо сказали:
Аватара пользователя
Naruto-kun
Сообщения: 228
Статус: небритый гентушник
ОС: Gentoo(PC)/easypeasy(Netbook)

Re: BASH

Сообщение Naruto-kun »

sash-kan писал(а):
14.05.2009 16:36
Naruto-kun писал(а):
14.05.2009 15:41
между данными в строке разное число пробелов
не понятно. т.е. в строке могут быть пропущенные поля?
ну, перед парсингом вставьте между двумя подряд идущими пробелами что-нибудь, что вам не помешает. например, «""»:
sed 's/ / "" /g'
в любом случае, будет быстрее читать одной встроенной командой read, нежели запуском пяти процессов echo и пяти процессов cut.
p.s. пока писал, вышло, что писал напрасно. оказывается, никаких скрытых смыслов и не было. вот так всегда… не обращаешь внимания на ник.

Ну, почему же напрасно, приму к сведению. Лишних советов не бывает.
PS. Последний вопрос, описанный в предыдущем посте пока до сих пор не решён. Скорость выполнения оставляет желать лучшего. Так, что буду рад любым предложениям.
Компьютер позволяет решать все те проблемы, которые до изобретения компьютера не существовали.
Если на вопрос ни кто не знает ответа, то пора читать описание.
Спасибо сказали:
Аватара пользователя
sash-kan
Администратор
Сообщения: 13939
Статус: oel ngati kameie
ОС: GNU

Re: BASH

Сообщение sash-kan »

ускорить немножко, конечно можно.
например, убрав вызовы sed, а замену точка/запятая возложив на awk, раз всё одно он вызывается.
но если время критично, возможно, имеет смысл сложить данные в базу данных.
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: BASH

Сообщение drBatty »

Naruto-kun писал(а):
14.05.2009 16:26
У меня реализовано так:

ИМХО либо sed, либо awk, либо bash...
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Naruto-kun
Сообщения: 228
Статус: небритый гентушник
ОС: Gentoo(PC)/easypeasy(Netbook)

Re: BASH

Сообщение Naruto-kun »

ускорить немножко, конечно можно.
например, убрав вызовы sed, а замену точка/запятая возложив на awk, раз всё одно он вызывается.
но если время критично, возможно, имеет смысл сложить данные в базу данных.

Спасибо, попробую. Правда, не совсем понятно как с помощью делать замены, подобные sed. Ладно погуглю. Кстати обнаружил странность для себя, в сравнении чисел. Вот например:

Код: Выделить всё

a=4,06
b=10
echo "$a $b" | awk '{if ($1 >= $2) print 1; else print 0}'

Здесь он, по условию должен выдать 0. Но почему-то выдаёт 1. Не могу понять причины.
UP: Кажется, что вся проблема была в запятой. Поставил вместо запятой точку и он выдал 0, как и должно быть.
Компьютер позволяет решать все те проблемы, которые до изобретения компьютера не существовали.
Если на вопрос ни кто не знает ответа, то пора читать описание.
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: BASH

Сообщение Zeus »

У меня есть строка состоящая из двух шестнадцатиричных цифр.



Требуется получить символ ASCII-кодом которого является значение переменной A.
Чем это делается?

=========
Кажется сам нашёл:

Код: Выделить всё

A="31"
printf "\x$A\n"

1


========
Ещё один вариант. От drBatty. BASH
Мне он кажется более универсальным: echo скорее всего на целевой платформе будет, а printf - неизвестно:

Код: Выделить всё

А="31"
echo -e "\x$A"

1
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: BASH

Сообщение drBatty »

Zeus писал(а):
20.05.2009 16:38
Кажется сам нашёл:

угу. printf универсальное средство. хотя используете вы его тут совсем весело :)
тут что угодно можно поставить

Код: Выделить всё

sed "s/.*/\x$A/;q" ~/.bashrc
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Zeus
Сообщения: 694

Re: BASH

Сообщение Zeus »

drBatty писал(а):
20.05.2009 20:19
Zeus писал(а):
20.05.2009 16:38
Кажется сам нашёл:

угу. printf универсальное средство. хотя используете вы его тут совсем весело :)

А что не так? :)

Я читаю данные из базы (mysql-клиентом), там поле blob с массивом значений.
Каждый байт - две шестнадцатеричные цифры. Нужно преобразовать в строку символов.
Вот я read'ом читаю по 2 символа и озадачился как полученный байт в виде двух цифр преобразовать в символ.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current

Re: BASH

Сообщение drBatty »

Zeus писал(а):
20.05.2009 21:51
А что не так?

ну у вас как-бы сказать...
на самом деле, вы получаете строку из строки, а потом строку считаете тоже строкой, только из шестнадцатеричных символов :)
А как вы эти BLOB'ы читаете? у меня почему-то получаются обычные символы...
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали: