URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 9959
[ Назад ]

Исходное сообщение
"Вернуть объект из функции на Shell. Чем заменить, как делают?"

Отправлено AV , 26-Дек-14 22:16 
В языках программирования функции могут возвращать "сложные" объекты. Массивы, хэши-словари. Есть что-то похожее для Shell (Bash, или иное)?

Я пробежался поиском - не увидел как сделать так, что код можно быстро будет понять через полчаса после написания. :)

Я так понимаю, что правильный ответ - Perl, с выключенными "предохранителями". Там можно всё нужное, да. Именно. Но вопрос таки про Bash или иной распространённый Shell.

Может быть есть какой-то известный, распространённый стиль/стратегия, которые позволяют обойтись?

Есть вот такой код (Bash 4):


#!/bin/bash

set -x
set -e

declare -r fileTmpA="/tmp/$( basename "${0}" )_A"
declare -r fileTmpB="/tmp/$( basename "${0}" )_B"
trap "rm '${fileTmpA}' '${fileTmpB}'" EXIT HUP INT TERM


################################################


declare -A dictionary_A
declare -A dictionary_B

echo -ne "0000\n1111\n" > "${fileTmpA}"
echo -ne "2222\n3333\n" > "${fileTmpB}"

while read value ; do
    key="$( echo "${value}" | md5sum | cut --delim=' ' --field 1 )"
    dictionary_A["${key}"]="${value}"
done <<< "$( cat "${fileTmpA}" )"

while read value ; do
    key="$( echo "${value}" | md5sum | cut --delim=' ' --field 1 )"
    dictionary_B["${key}"]="${value}"
done <<< "$( cat "${fileTmpB}" )"


################################################


set +x
echo "________________________________________________"
for key in "${!dictionary_A[@]}" "${!dictionary_B[@]}" ; do
    echo "Have key: ${key}"
done


А теперь фейковый вариант.
Bash так не умеет,
но это пример того,
какой примерно инструмент хотелось бы.
Хочется использовать какой-то код типа такого:


#!/bin/bash

set -x
set -e

declare -r fileTmpA="/tmp/$( basename "${0}" )_A"
declare -r fileTmpB="/tmp/$( basename "${0}" )_B"
trap "rm '${fileTmpA}' '${fileTmpB}'" EXIT HUP INT TERM


################################################


function fillDictFromFile {
    local -r fileName
    local -A dictionary
    while read string ; do
        key="$( echo "${string}" | md5sum | cut --delim=' ' --field 1 )"
        dictionary["${key}"]="${value}"
    done <<< "$( cat "${fileName}" )"
    return dictionary
}


echo -ne "0000\n1111\n" > "${fileTmpA}"
echo -ne "2222\n3333\n" > "${fileTmpB}"

declare -A dictionary_A="$( fillDictFromFile "${fileTmpA}" )"
declare -A dictionary_B="$( fillDictFromFile "${fileTmpB}" )"


################################################


set +x
echo "________________________________________________"
for key in "${!dictionary_A[@]}" "${!dictionary_B[@]}" ; do
    echo "Have key: ${key}"
done

Как делают? Perl, C и т.д.  :) :) - да, я знаю их и др. А вот есть ли что-то для Shell?


Содержание

Сообщения в этом обсуждении
"Вернуть объект из функции на Shell. Чем заменить, как делают?"
Отправлено pavlinux , 28-Дек-14 01:04 
> Bash так не умеет,


#!/bin/bash

set -e
set -x

fileTmpA="/tmp/$(basename $0)_A"
fileTmpB="/tmp/$(basename $0)_B"

trap "rm $fileTmpA $fileTmpB" EXIT HUP INT TERM

################################################

function fDFF {

    local i=0;
    local -a dict=();

    for string in $(cat $1)
        do
           key=$(echo $string | md5sum | cut -d' ' -f1);
           dict[$i]=$key;
           ((i++));
    done;
echo ${dict[@]}
}

echo -ne "0000\n1111" > $fileTmpA;
echo -ne "2222\n3333" > $fileTmpB;

declare -a dictionary_A=($(fDFF $fileTmpA));
declare -a dictionary_B=($(fDFF $fileTmpB));

################################################

echo "________________________________________________"

for key in "${dictionary_A[@]}" "${dictionary_B[@]}" ;
   do
        echo "Have key: ${key}"
done


________________________________
Have key: 4c3cbcadf7b8a9ae2932afc00560a0d6
Have key: 1f18348f32c9a4694f16426798937ae2
Have key: 9dc23e23a84232dd4e5919863161285c
Have key: 4fb7e693a03d73ab460a97e3f92fd20b

"Вернуть объект из функции на Shell. Чем заменить, как делают?"
Отправлено AV , 28-Дек-14 15:32 
Если в строках будут пробелы, спец. символы и инструкции Shell или esc последовательности - оно сломается ведь?

Интересно словарь "вернуть" из функции. Не просто массив,
declare -a ARRAY=(E1 E2 …)
а словарь
declare -A ARRAY=([X]=E1 [Y]=E2 …)

Если "${dict[@]}" разворачивается как независимые строки, по одной строке на элемент, то приставка echo склеивает всё в одну строку. Потеря информации.

Можно пытаться расставлять экраны и кавычки/апострофы, но не знаю простого и читаемого способа сделать это. Хорошо бы ещё и быстрого, т.к. вызов sed и т.п. довольно долго происходит.


"Вернуть объект из функции на Shell. Чем заменить, как делают?"
Отправлено pavlinux , 29-Дек-14 21:43 
> Хорошо бы ещё и быстрого, т.к. вызов sed и т.п. довольно долго происходит.

Хе... Вот те задачка на ассоциативные массивы:

Заменить в тексте все буквы русского алфавита на схожие по-написанию латинские. Только bash.

#!/bin/bash

RUS_CAP=(А В Е К М Н О Р С Т Х)
LAT_CAP=(A B E K M H O P C T X)

RUS_LET=(а е о р с у х)
LAT_LET=(a e o p c y x)

Текст:
http://vojnaimir.ru/files/book1.txt.zip
http://vojnaimir.ru/files/book2.txt.zip

$ unzip -c book1.txt.zip | iconv -f cp1251 -t utf8 > BOOK.txt
$ unzip -c book2.txt.zip | iconv -f cp1251 -t utf8 >> BOOK.txt

$ time cat BOOK.txt | convert.sh;

и показываешь тут время.

---
В гугл не подсматривать.

----

Ну чтоб сразу расстроился :-P

$ time cat BOOK.txt | sed 'y/АВЕКМНОРСТХаеорсух/ABEKMHOPCTXaeopcyx/' > bebebe

real    0m1.593s
user    0m1.565s
sys     0m0.036s


"Вернуть объект из функции на Shell. Чем заменить, как делают?"
Отправлено fantom , 30-Дек-14 18:14 
>[оверквотинг удален]
> последовательности - оно сломается ведь?
> Интересно словарь "вернуть" из функции. Не просто массив,
> declare -a ARRAY=(E1 E2 …)
> а словарь
> declare -A ARRAY=([X]=E1 [Y]=E2 …)
> Если "${dict[@]}" разворачивается как независимые строки, по одной строке на элемент, то
> приставка echo склеивает всё в одну строку. Потеря информации.
> Можно пытаться расставлять экраны и кавычки/апострофы, но не знаю простого и читаемого
> способа сделать это. Хорошо бы ещё и быстрого, т.к. вызов sed
> и т.п. довольно долго происходит.

\r добавляешь в конец каждого элемента, и echo нарисует как надо..