Вопрос по bash-scripting (переменные и подстановка)

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

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

Аватара пользователя
agent-mega
Сообщения: 505
Статус: Автономный модуль

Вопрос по bash-scripting

Сообщение agent-mega »

Вообщем, допустим, есть переменные:
A1=50
A2=100
Скрипт откуда-то (неважно) получает переменную $x, равную либо 1, либо 2.
В зависимости от x, скрипт должен выводить "Ax" равным либо 50, либо 100.
Как определять это самое "Ax" через синтаксис? Т.е. нужно, грубо говоря, к строковому значению, к букве "A" присобачить рядом значение x и сказать, что вместе всё это - переменная.
Что-то в духе ${A$x} или ${A`echo $x`} не помогает - bad substitution.

Курил Advanced Bash-Scripting Guide. Не накурился. Или плохо курил. Или туплю.
Подскажите.

ЗЫ. Уй, опять не туда, в Программирование хотел <_<
DEBIAN & DEBIAN-BASED ONLY

Всё относительно. Объективности не существует.
Спасибо сказали:
Аватара пользователя
elide
Бывший модератор
Сообщения: 2421
Статус: Übermensch
ОС: лялих

Re: Вопрос по bash-scripting

Сообщение elide »

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

eval echo \$A$x
слава роботам!
Спасибо сказали:
Аватара пользователя
agent-mega
Сообщения: 505
Статус: Автономный модуль

Re: Вопрос по bash-scripting

Сообщение agent-mega »

(elide @ Пятница, 22 Июля 2005, 17:46) писал(а):

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

eval echo \$A$x


Спасибо :)
DEBIAN & DEBIAN-BASED ONLY

Всё относительно. Объективности не существует.
Спасибо сказали:
Аватара пользователя
sash-kan
Администратор
Сообщения: 13939
Статус: oel ngati kameie
ОС: GNU

Re: Вопрос по bash-scripting

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

echo $[A$x]
Писать безграмотно - значит посягать на время людей, к которым мы адресуемся, а потому совершенно недопустимо в правильно организованном обществе. © Щерба Л. В., 1957
при сбоях форума см.блог
Спасибо сказали:
Аватара пользователя
agent-mega
Сообщения: 505
Статус: Автономный модуль

Re: Вопрос по bash-scripting

Сообщение agent-mega »

(Sash Kan @ Пятница, 22 Июля 2005, 18:03) писал(а):echo $[A$x]

О, ещё короче :P Я был близок :)
DEBIAN & DEBIAN-BASED ONLY

Всё относительно. Объективности не существует.
Спасибо сказали:
Аватара пользователя
agent-mega
Сообщения: 505
Статус: Автономный модуль

Re: Вопрос по bash-scripting

Сообщение agent-mega »

Вопрос следующего порядка:
Как в строковую переменную $STRING записать ИМЯ переменной $[A$i] ? Как сделать так, чтобы в следующий раз, когда $i станет другим, имя $[A$i] ДОБАВЛЯЛОСЬ, а не перезаписывалось в строку $STRING? Вообщем, должна получится срока, содержащая имена переменных.

Т.е., например у нас $STRING равна 'A1', потом мы говорим что-то волшебное и она становится равна 'A1 A2', потом 'A1 A2 A3'...
DEBIAN & DEBIAN-BASED ONLY

Всё относительно. Объективности не существует.
Спасибо сказали:
Аватара пользователя
t.t
Бывший модератор
Сообщения: 7390
Статус: думающий о вечном
ОС: Debian, LMDE

Re: Вопрос по bash-scripting

Сообщение t.t »

А какая, собственно, разница, имя это переменно или не имя? Что-то такое имеется ввиду?

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

STRING=""
for i in `seq 5`; do
  STRING="$STRING \$A$i"
done
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
Спасибо сказали:
Аватара пользователя
agent-mega
Сообщения: 505
Статус: Автономный модуль

Re: Вопрос по bash-scripting

Сообщение agent-mega »

t.t писал(а):
16.01.2006 19:20
А какая, собственно, разница, имя это переменно или не имя? Что-то такое имеется ввиду?

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

STRING=""
for i in `seq 5`; do
  STRING="$STRING \$A$i"
done

В этом коде в STRING будет $A1 $A2 $A3 $A4 $A5. А мне нужно было, чтобы было A1 A2 A3 A4 A5.
Если написать STRING="$STRING \A$i", то будет \A1 \A2 \A3 \A4 \A5 ...
Мне нужно, чтобы попадало только имя переменной.
Разница в том, что мне нужно будет чтобы в строку попадали только имена переменных, отвечающих определённому условию.

ЗЫ. Кстати, интересно, есть такая функция, которая возвращает имя переменной если ей дать в качестве аргумента эту переменную? :) А в других языках?
DEBIAN & DEBIAN-BASED ONLY

Всё относительно. Объективности не существует.
Спасибо сказали:
Аватара пользователя
madskull
Сообщения: 1019
Статус: Экс-металлюга

Re: Вопрос по bash-scripting

Сообщение madskull »

Ну так убери \$ из ответа Тихона.
Т.е. STRING="$STRING A$i"
ArchLinux / IceWM
Спасибо сказали:
Аватара пользователя
elide
Бывший модератор
Сообщения: 2421
Статус: Übermensch
ОС: лялих

Re: Вопрос по bash-scripting

Сообщение elide »

кстати, тут ходят слухи, что синтаксис $[A$x] - deprecated. надо юзать $((A$x))
слава роботам!
Спасибо сказали:
Аватара пользователя
agent-mega
Сообщения: 505
Статус: Автономный модуль

Re: Вопрос по bash-scripting

Сообщение agent-mega »

кстати, тут ходят слухи, что синтаксис $[A$x] - deprecated. надо юзать $((A$x)

А можно поподробнее? Кем осуждается-то такой синтаксис?

P.S. Проблема со строками опять:
Пишу:

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

x=1
let A$x=100
echo $A1
echo $((A$x))

#bash :
100
100
Пишу:

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

x=1
let A$x=bla
echo $A1
echo $((A$x))

#bash :
0
0

Что за?... Пробовал и с квадратными - тоже самое. Похоже, с помощью let можно задавать только числа? Но ведь в bash нет типов переменных! А чем мне тогда ещё заменить let A$x=bla ???
DEBIAN & DEBIAN-BASED ONLY

Всё относительно. Объективности не существует.
Спасибо сказали:
Аватара пользователя
madskull
Сообщения: 1019
Статус: Экс-металлюга

Re: Вопрос по bash-scripting

Сообщение madskull »

agent-mega писал(а):
19.01.2006 18:16
Что за?... Пробовал и с квадратными - тоже самое. Похоже, с помощью let можно задавать только числа? Но ведь в bash нет типов переменных! А чем мне тогда ещё заменить let A$x=bla ???

как ни странно - man bash.
И let, и $((...)) - работа с арифметикой

Как замена - eval


agent-mega писал(а):
19.01.2006 18:16
кстати, тут ходят слухи, что синтаксис $[A$x] - deprecated. надо юзать $((A$x)

А можно поподробнее? Кем осуждается-то такой синтаксис?

Опять таки man bash и пробуем найти $[ ... Нету!
ArchLinux / IceWM
Спасибо сказали:
Аватара пользователя
Kuzja
Сообщения: 675
Статус: розовая хрюшка

Re: Вопрос по bash-scripting

Сообщение Kuzja »

У меня тоже вопрос: каким образом принимать ключи и параметри, напрмер "--help"?
/Ubuntu-Dapper6/Xorg7.0/GNOME-2.14.1/
Спасибо сказали:
Аватара пользователя
agent-mega
Сообщения: 505
Статус: Автономный модуль

Re: Вопрос по bash-scripting

Сообщение agent-mega »

Опять таки man bash и пробуем найти $[ ... Нету!

В man bash, что, есть ВСЁ? С трудом верится.
И let, и $((...)) - работа с арифметикой

Не знал.
Как замена - eval

eval [аргумент ...]
Аргументы читаются и соединяются в единую команду. Эта команда затем читается и выполняется командным интерпретатором, а ее статус выхода возвращается в качестве значения команды eval. Если аргументов нет или все аргументы пустые, команда eval возвращает 0.

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

x=2
eval A$x=bla

Работает.

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

x=2
A$x=bla

Не работает.
Я не понимаю тогда, чем отличается "eval команда" от просто "команда"... Без eval команда что, не "читается и выполняется командным интерпретатором" ??

У меня тоже вопрос: каким образом принимать ключи и параметри, напрмер "--help"?

Всмысле "как принимать"? В скрипте ключи и параметры команды специально экранировать обычно не надо. По крайней мере, у меня с этим трудностей нет. Как есть, так и пишешь. Или я не так понял?
DEBIAN & DEBIAN-BASED ONLY

Всё относительно. Объективности не существует.
Спасибо сказали:
Аватара пользователя
Kuzja
Сообщения: 675
Статус: розовая хрюшка

Re: Вопрос по bash-scripting

Сообщение Kuzja »

Всмысле "как принимать"? В скрипте ключи и параметры команды специально экранировать обычно не надо. По крайней мере, у меня с этим трудностей нет. Как есть, так и пишешь. Или я не так понял?

Я имел в виду, если в командной строке пишется my_script --some_key, то каким образом обработать этот самый some_key в скрипте?
/Ubuntu-Dapper6/Xorg7.0/GNOME-2.14.1/
Спасибо сказали:
Аватара пользователя
Portnov
Модератор
Сообщения: 1786
Статус: Матёрый линуксоид
ОС: Debian testing/unstable

Re: Вопрос по bash-scripting

Сообщение Portnov »

1. По eval. При 'eval command' сначала выполняются все подстановки в command, после чего результат оказывается входной строкой, т.е. опять выполняются подстановки и команда выполняется.
Пример:

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

$ A=x
$ B=A
$ echo $"$B"
> $A
$ eval echo $"$B"
> x


2. Про опции - man getopt.
Работа: Ubuntu 9.10
Дом: Debian testing/unstable и на всякий случай winxp в virtualbox.
Для разнообразия: моя домашняя страница -http://iportnov.ru
Спасибо сказали:
Аватара пользователя
Kuzja
Сообщения: 675
Статус: розовая хрюшка

Re: Вопрос по bash-scripting

Сообщение Kuzja »

Portnov
спасибо
/Ubuntu-Dapper6/Xorg7.0/GNOME-2.14.1/
Спасибо сказали:
Аватара пользователя
kusok
Сообщения: 306
Статус: laid to rest
ОС: Debian Sid

Re: Вопрос по bash-scripting

Сообщение kusok »

Kuzja писал(а):
19.01.2006 20:47
Я имел в виду, если в командной строке пишется my_script --some_key, то каким образом обработать этот самый some_key в скрипте?

Для этого есть специальные переменные, типа $1 $2 etc.
Например:

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

#!/bin/sh
echo $1
echo $2

При запуске с аргументами выдаст следующее:

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

[kusok@localhost]~% ./example.sh --some-key --some-key2
--some-key
--some-key2
Спасибо сказали:
Аватара пользователя
agent-mega
Сообщения: 505
Статус: Автономный модуль

Re: Вопрос по bash-scripting

Сообщение agent-mega »

2Portnov: благодарю, теперь понял.

Насчёт $1, $2 - дополню: так же удобно использовать их в функциях:

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

function ()
{
echo "$1"
}
function a

#bash:
a
DEBIAN & DEBIAN-BASED ONLY

Всё относительно. Объективности не существует.
Спасибо сказали:
Аватара пользователя
madskull
Сообщения: 1019
Статус: Экс-металлюга

Re: Вопрос по bash-scripting

Сообщение madskull »

agent-mega писал(а):
19.01.2006 20:23
Опять таки man bash и пробуем найти $[ ... Нету!

В man bash, что, есть ВСЁ? С трудом верится.

Ну, утверждать не берусь, но почему там не должно быть ВСЕГО? Это же справка и все команды и синтаксис там должны быть расписаны.


Не поленился и скачал bash-1.14.7 - там в мане есть упоминание про $[expression], а в двойке уже нет.
ArchLinux / IceWM
Спасибо сказали:
uZer
Сообщения: 100

Re: Вопрос по bash-scripting

Сообщение uZer »

Помогите пжл.
есть в файле строка с пробелами (например "1 555[123] 000") как выцепить из нее цифры, находящиеся в [] ?
спасибо
Спасибо сказали:
Аватара пользователя
madskull
Сообщения: 1019
Статус: Экс-металлюга

Re: Вопрос по bash-scripting

Сообщение madskull »

uZer писал(а):
25.01.2006 21:43
Помогите пжл.
есть в файле строка с пробелами (например "1 555[123] 000") как выцепить из нее цифры, находящиеся в [] ?
спасибо

Один из вариантов:

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

sed 's/.*\[\([0-9]*\)\].*/\1/'
ArchLinux / IceWM
Спасибо сказали:
Аватара пользователя
elide
Бывший модератор
Сообщения: 2421
Статус: Übermensch
ОС: лялих

Re: Вопрос по bash-scripting

Сообщение elide »

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

perl -nle 'print$1if/\[(\d+)\]/'
чуть длиннее, зато работает в 6 раз быстрее.
слава роботам!
Спасибо сказали:
uZer
Сообщения: 100

Re: Вопрос по bash-scripting

Сообщение uZer »

madskull писал(а):
25.01.2006 22:58
Один из вариантов:

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

sed 's/.*\[\([0-9]*\)\].*/\1/'


ниасилил, хотя долго-долго курил man sed.....
можно пояснить строку?
Спасибо сказали:
Аватара пользователя
Warderer
Модератор
Сообщения: 1056
Статус: киберпИнгвин на гусеничном ходу
ОС: Debian unstable

Re: Вопрос по bash-scripting

Сообщение Warderer »

Надо курить не man sed, а посмотреть на регулярные выражения. Расшифровываю:
s/<выражение>/<выражение>/ - оператор замены
.* - любой символ (.) любое количество раз, включая нулевое (квантификатор *)
\[ - экранированная открывающая кавычка
\(<выражение>\) - выделение совпадения в переменную
[0-9]* - любое количество цифр (хм, а что в sed нет символа \d ?)
\1 - переменная, полученная скобками (на две строки выше)

madskull я всё так сказал?
Читаю вслух с выражением маны - $50/ч + стоимость звонка. Настраиваю сервисы за Вас - $100/ч + стоимость выезда и проживания.
И восемь строк матом...(бесплатно)
Спасибо сказали:
Аватара пользователя
madskull
Сообщения: 1019
Статус: Экс-металлюга

Re: Вопрос по bash-scripting

Сообщение madskull »

Warderer писал(а):
26.01.2006 11:57
madskull я всё так сказал?

Да.

Warderer писал(а):
26.01.2006 11:57
[0-9]* - любое количество цифр (хм, а что в sed нет символа \d ?)

Нет, в нем много чего нет.
ArchLinux / IceWM
Спасибо сказали:
Аватара пользователя
madskull
Сообщения: 1019
Статус: Экс-металлюга

Re: Вопрос по bash-scripting

Сообщение madskull »

elide писал(а):
26.01.2006 04:41

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

perl -nle 'print$1if/\[(\d+)\]/'
чуть длиннее, зато работает в 6 раз быстрее.

А с чего взяты такие данные?

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

[arena ~]$ time for i in `seq 1000`; do echo "1 555[123] 000" | sed 's/.*\[\([0-9]*\)\].*/\1/' > /dev/null; done

real    0m12.532s
user    0m8.393s
sys     0m4.057s
[arena ~]$ time for i in `seq 1000`; do echo "1 555[123] 000" | perl -nle 'print$1if/\[(\d+)\]/' > /dev/null; done

real    0m17.739s
user    0m10.835s
sys     0m5.809s
[arena ~]$

Конечно, это не тянет на лабораторные тесты и, хотя, результат прыгал +-2 сек, но кое-что показывает.
ArchLinux / IceWM
Спасибо сказали:
Аватара пользователя
Sparky
Сообщения: 604
Статус: core dumped
ОС: Plan 9

Re: Вопрос по bash-scripting

Сообщение Sparky »

А вот так быстрее:

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

$ for i in `seq 1000`; do echo "1 555[123] 000"; done > testfile

$time  sed 's/.*\[\([0-9]*\)\].*/\1/' < testfile > /dev/null

real    0m0.015s
user    0m0.013s
sys     0m0.002s

$time  perl -nle 'print$1if/\[(\d+)\]/' < testfile > /dev/null


real    0m0.006s
user    0m0.004s
sys     0m0.003s

но это и логично, Perl тяжеловеснее sed.

Кстати вот вам и оптимизация:

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

меняем
$time for i in `seq 1000`; do echo "1 555[123] 000" | perl -nle 'print$1if/\[(\d+)\]/' > /dev/null; done
на
time for i in `seq 1000`; do echo "1 555[123] 000"; done | perl -nle 'print$1if/\[(\d+)\]/' > /dev/null

работает в 30! раз быстрее в среднем B)
Блог
--------------------

GCS/M/MU/P/IT/E d- s: a- C++(+++) UBL++ P->-- L+++$ E- W+++$ N* o? K? w>--
O M-@ V- PS@ PE+ Y+ PGP+ t 5 X R* tv-->- b++ DI? D>+ G e+(++) h--- r+ y++
Спасибо сказали:
Аватара пользователя
elide
Бывший модератор
Сообщения: 2421
Статус: Übermensch
ОС: лялих

Re: Вопрос по bash-scripting

Сообщение elide »

madskull, просто не надо много-много раз запускать перл. тогда конечно не будет скорости, но так его никто и не использует.... скорость проверяется на больших потоках данных. хотя бы так:

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

elide@rebirth| ~ >> seq 1 1000000 | while read i; do echo "1 555[$i] 000"; done > file
elide@rebirth| ~ >> ll file
-rw-------  1 elide users 18M 2006-01-26 16:54 file
elide@rebirth| ~ >> time perl -nle 'print$1if/\[(\d+)\]/' file > /dev/null

real    0m3.375s
user    0m3.167s
sys     0m0.041s
elide@rebirth| ~ >> time sed 's/.*\[\([0-9]*\)\].*/\1/' file > /dev/null

real    0m20.367s
user    0m19.577s
sys     0m0.074s
elide@rebirth| ~ >>
20.367/3.375 = 6.0347.
ч.т.д.

и это на каком-то жалком миллионе записей.....
и, да. битые записи.

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

elide@rebirth| ~ >> cat file
1 555[1] 000
1 555[] 000
1 555[q3] 000
1 555[4 ] 000
1 5555] 000
1 555[6 000
1 555[7] 000
elide@rebirth| ~ >> sed 's/.*\[\([0-9]*\)\].*/\1/' file
1

1 555[q3] 000
1 555[4 ] 000
1 5555] 000
1 555[6 000
7
elide@rebirth| ~ >> perl -nle 'print$1if/\[(\d+)\]/' file
1
7
elide@rebirth| ~ >>
слава роботам!
Спасибо сказали:
Аватара пользователя
madskull
Сообщения: 1019
Статус: Экс-металлюга

Re: Вопрос по bash-scripting

Сообщение madskull »

Я не спорю, что "в себе" перл будет быстрее. И удобнее.
Но, господа, посмотрите на тему! Вопрос по bash-scripting! То есть, если и используем перл, то в конвейере с другими командами. И про скорость танцуем тоже от конвейера.
И вообще -- это уже оффтоп.
ArchLinux / IceWM
Спасибо сказали: