LinuxForum.Fans
Тема

Не могу правильно разбить строку на аргументы

Автор: Moritto 15 сообщений 1277 просмотров
24.06.2017 20:52 #423833

Я изучил bash язык, но теперь я не понимаю как разбить строку так как мне нужно.
Вот программа:

text

#!/system/bin/bash

DB=millioner.db #файл базы данных в читабельном формате

[ ! -f $DB ] && echo "Файл базы данных $DB не найден" && exit 70

loadDB() { lines=$(cat $DB | wc -l) [ "$lines" -eq 0 ] && echo "Файл базы данных пустой!" && exit 71 while read line; do set "$line" echo $1 echo $2 echo $3 echo $4 echo $5 echo $6 done < $DB }

loadDB

На консоль ыводит вот такую ерунду:
[console]
"Сколько мегабайт оперативной памяти содержится в 4 гб?" "4000 мб" "4096 мб" "4032 мб" "3996 мб" 2






[/console]
В файле millioner.db у меня следующее:

text

"Сколько мегабайт оперативной памяти содержится в 4 гб?" "4000 мб" "4096 мб" "4032 мб" "3996 мб" 2

Мне нужно чтобы записывалось 5 аргументов из этого файла которые в кавычках, а затем выводились на экран, но как вы видите у меня ничего не получилось. Я ещё попробовал вот так:

text

set -- $line

и вот что я видел при выполнении:
[console]
"Сколько
мегабайт
оперативной
памяти
содержится
в
[/console]
Как видите это совсем не то что я хотел получить. Помогите с решением только без всяких вспомогательных программ sed,awk, потому что у меня только Android и всё, а тут никто их не додумался портировать

24.06.2017 21:35 #423836

Так по-моему и настоящего bash на android нет. По-моему там вообще busybox. У shell-ов вообще куча вариантов, несовместимых между собой, пусть и по мелочи. Зато есть полновесная java :)
Да и не уверен я, что set от bash обязан правильно разбирать подобные конструкции. Тут, возможно, eval поможет. Правда я это уже лет 30 не делал.

25.06.2017 00:10 #423838

[console]$ cat millioner.db |tr '"' '\n'|grep -v '^[[:space:]]*$'[/console]
?

25.06.2017 09:03 #423844

Только средства bash:

text
#!/bin/bash

AA=$(cat millioner.db) i=0 while read file do if [ "$file" != "" ] ; then mass[$[i++]]="$file" fi done <<< $(echo -e ${AA//\"/\\n})

i=0 n=${#mass[@]} while [ $i != $n ] do echo ${mass[$[i++]]} done

25.06.2017 09:51 · отредактировано #423845

Так поменяй формат Бд:

Сколько мегабайт оперативной памяти содержится в 4 гб?|4000 мб|4096 мб|4032 мб|3996 мб

и cut -d '|' -f1,2, ..

Помогите с решением только без всяких вспомогательных программ sed,awk, потому что у меня только Android и всё, а тут никто их не додумался портировать

а, все забываю.
Тогда только это: http://tldp.org/LDP/abs/html/string-manipulation.html

25.06.2017 15:43 #423855
s.xbatob написал:
Так по-моему и настоящего bash на android нет. По-моему там вообще busybox. У shell-ов вообще куча вариантов, несовместимых между собой, пусть и по мелочи. Зато есть полновесная java :)
Да и не уверен я, что set от bash обязан правильно разбирать подобные конструкции. Тут, возможно, eval поможет. Правда я это уже лет 30 не делал.

Я скомпилировал полную версию, вот ссылка https://github.com/gromnitsky/bash-on-android
Все работает

25.06.2017 15:52 #423856
ormorph написал:
Только средства bash:
text
#!/bin/bash

AA=$(cat millioner.db) i=0 while read file do if [ "$file" != "" ] ; then mass[$[i++]]="$file" fi done <<< $(echo -e ${AA//\"/\\n})

i=0 n=${#mass[@]} while [ $i != $n ] do echo ${mass[$[i++]]} done

Такой код выдает ошибку
[console]
app_105 BASH $ ./milioner2.sh
./milioner2.sh: line 5: read: read error: 0: No such file or directory
Сколько мегабайт оперативной памяти содержится в 4 гб?
[/console]
Да и слишком громоздко

25.06.2017 16:18 #423857
1000Mhz написал:
Так поменяй формат Бд:

Сколько мегабайт оперативной памяти содержится в 4 гб?|4000 мб|4096 мб|4032 мб|3996 мб

и cut -d '|' -f1,2, ..

cut быстро раьотает, на нем сделаю.

25.06.2017 16:31 #423858
Moritto написал:
[quote=ormorph]Только средства bash:
text
#!/bin/bash

AA=$(cat millioner.db) i=0 while read file do if [ "$file" != "" ] ; then mass[$[i++]]="$file" fi done <<< $(echo -e ${AA//\"/\\n})

i=0 n=${#mass[@]} while [ $i != $n ] do echo ${mass[$[i++]]} done

Такой код выдает ошибку
[console]
app_105 BASH $ ./milioner2.sh
./milioner2.sh: line 5: read: read error: 0: No such file or directory
Сколько мегабайт оперативной памяти содержится в 4 гб?
[/console]
Да и слишком громоздко[/quote]
Значит что то изменили, например переменную AA

25.06.2017 17:06 #423860
ormorph написал:
[quote=Moritto][quote=ormorph]Только средства bash:
text
#!/bin/bash

AA=$(cat millioner.db) i=0 while read file do if [ "$file" != "" ] ; then mass[$[i++]]="$file" fi done <<< $(echo -e ${AA//\"/\\n})

i=0 n=${#mass[@]} while [ $i != $n ] do echo ${mass[$[i++]]} done

Такой код выдает ошибку
[console]
app_105 BASH $ ./milioner2.sh
./milioner2.sh: line 5: read: read error: 0: No such file or directory
Сколько мегабайт оперативной памяти содержится в 4 гб?
[/console]
Да и слишком громоздко[/quote]
Значит что то изменили, например переменную AA[/quote]
Я не менял, создал новый файл и закинул туда этот скрипт со своей шабангой.

25.06.2017 17:26 #423861
"Moritto" написал:
Я не менял, создал новый файл и закинул туда этот скрипт со своей шабангой.

Значит все зависит от реализации bash, этот скрипт тестировал на android termux, на нем работало норм, сейчас попробовал под linux, тут незначительно переделать пришлось, добавить кавычки, иначе не так работал:

text
#!/bin/bash

AA=$(cat millioner.db) #Заполнение массива в цикле i=0 while read file do if [ "$file" != "" ] ; then mass[$[i++]]="$file" fi done <<< "$(echo -e ${AA//\"/\\n})"

# вывод массива в цикле i=0 n=${#mass[@]} while [ $i != $n ] do echo ${mass[$[i++]]} done

А так громоздкость тут из за того что заполняется в одном цикле а выводится в другом, можно сделать значительно короче, например так:

text
#!/bin/bash

AA=$(cat millioner.db) i=0 while read file do if [ "$file" != "" ] ; then mass[$i]="$file" echo ${mass[$[i++]]} fi done <<< "$(echo -e ${AA//\"/\\n})"

25.06.2017 20:44 #423863
ormorph написал:
[quote="Moritto"]Я не менял, создал новый файл и закинул туда этот скрипт со своей шабангой.

Значит все зависит от реализации bash, этот скрипт тестировал на android termux, на нем работало норм, сейчас попробовал под linux, тут незначительно переделать пришлось, добавить кавычки, иначе не так работал:

text
#!/bin/bash

AA=$(cat millioner.db) #Заполнение массива в цикле i=0 while read file do if [ "$file" != "" ] ; then mass[$[i++]]="$file" fi done <<< "$(echo -e ${AA//\"/\\n})"

# вывод массива в цикле i=0 n=${#mass[@]} while [ $i != $n ] do echo ${mass[$[i++]]} done

А так громоздкость тут из за того что заполняется в одном цикле а выводится в другом, можно сделать значительно короче, например так:

text
#!/bin/bash

AA=$(cat millioner.db) i=0 while read file do if [ "$file" != "" ] ; then mass[$i]="$file" echo ${mass[$[i++]]} fi done <<< "$(echo -e ${AA//\"/\\n})"

[/quote]
У меня 4.4.0 beta.
У меня строки разделены слэшэм и поэтому я сделал вот как:
[console]
#!/system/bin/bash


AA=$(cat millioner.db)
i=0
while read file
do
if [ "$file" != "" ] ; then
mass[$i]="$file"
echo ${mass[$[i++]]}
fi
done <<< ${AA/////\\n}

[/console]
Так у меня хотя бы прочиталось две строки
[console]
ctory
app_105 BASH $ ./test.sh
Сколько мегабайт оперативной памяти содержится в 4 гб?/n4000 мб/n4096 мб/n4032 мб/n3996 мб/n2
Как зовут создателя синего ящика?/nСтив Джобс/nДональд Трамп/nКапитан Кранч/nPar/n3
./test.sh: line 6: read: read error: 0: No such file or directory
[/console]
Но последнюю строчку он прочитать не смог

25.06.2017 20:59 · отредактировано #423864

Ну вообще в bash есть массивы, которые уже представляют готовую структуру. Остается только привести файл millioner.db к такому виду:

text
MASS=("Сколько мегабайт оперативной памяти содержится в 4 гб?" "4000 мб" "4096 мб" "4032 мб" "3996 мб" 2)

соответственно считывать можно так:

text
#!/bin/bash

source millioner.db i=0 n=${#MASS[@]} while [ $i != $n ] do echo ${MASS[$[i++]]} done

И не надо мучатся с обработкой файла, если предполагается использовать множество вариантов в одной базе, то просто в файле millioner.db использовать выбор в конструкции case.
Получается все довольно просто и ни чего лишнего...

25.06.2017 22:53 #423867
ormorph написал:
Ну вообще в bash есть массивы, которые уже представляют готовую структуру. Остается только привести файл millioner.db к такому виду:
text
MASS=("Сколько мегабайт оперативной памяти содержится в 4 гб?" "4000 мб" "4096 мб" "4032 мб" "3996 мб" 2)

соответственно считывать можно так:

text
#!/bin/bash

source millioner.db i=0 n=${#MASS[@]} while [ $i != $n ] do echo ${MASS[$[i++]]} done

И не надо мучатся с обработкой файла, если предполагается использовать множество вариантов в одной базе, то просто в файле millioner.db использовать выбор в конструкции case.
Получается все довольно просто и ни чего лишнего...

Я потом проверю подходит ли этот вариант для моей игры.

25.06.2017 23:15 #423868
"Moritto" написал:
Я потом проверю подходит ли этот вариант для моей игры.

Да вот пример, у меня работает.
cat millioner.db:

text
case $variant in
   0) MASS=("Сколько мегабайт оперативной памяти содержится в 4 гб?" "4000 мб" "4096 мб" "4032 мб" "3996 мб" 2) 
      ;;
   1) MASS=("Как зовут создателя синего ящика?" "Стив Джобс" "Дональд Трамп" "Капитан Кранч Par" 1)
      ;;
esac

Демо игра:

text
#!/bin/bash

f_variant() { variant=$1 source millioner.db }

f_out() { i=0 n=${#MASS[@]} while [ $i != $[n-1] ] do if [ $i = 0 ] ; then echo ${MASS[$[i++]]} else printf "$i) ${MASS[$[i++]]}\n" fi done } f_game() { echo printf "введите вариант " ;read A if [ "${MASS[$[n-1]]}" = "$A" ] ; then clear echo Верно! read else clear echo "Не верно!" echo "Правильный ответ (${MASS[${MASS[$[n-1]]}]})" read fi }

clear f_variant 0 f_out f_game

clear f_variant 1 f_out f_game

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