2016-12-19 5 views
1

Я делаю функцию, чтобы легко преобразовать мои строки в массивы, как мне нужно.установка позиционного параметра в функции в bash

Я немного запутался в странную проблему. Я до сих пор новичок в bash, и это действительно подталкивает меня. Кто-нибудь сможет пролить свет на это?

convert.sh

#!/bin/bash 
convert2array() { 
read -a $1_arr <<< $1 
} 

mx=$(dig +short google.com mx | cut -d' ' -f 2 | sed 's/\.$//') 

convert2array "$mx" 

echo ${mx_arr[@]} 

Выход:

bash -x convert2array.sh 
++ sed 's/\.$//' 
++ cut '-d ' -f 2 
++ dig +short google.com mx 
+ mx='alt2.aspmx.l.google.com 
alt3.aspmx.l.google.com 
alt1.aspmx.l.google.com 
aspmx.l.google.com 
alt4.aspmx.l.google.com' 
+ convert2array mx 
+ read -a mx_arr 
+ echo 585911 
585911 

ответ

2

Вы можете непосредственно хранить результаты в массиве

declare -a results=($(dig +short google.com mx | cut -d' ' -f 2 | sed 's/\.$//')) 
echo "${results[@]}" 

Кроме того, вам не нужно использовать cut здесь, sed одного достаточно.

declare -a results=($(dig +short google.com mx | sed -E 's/^[[:digit:]]*[[:blank:]]*(.*)\.$/\1/')) 
echo "${results[@]}" 
aspmx.l.google.com 
alt1.aspmx.l.google.com 
alt2.aspmx.l.google.com 
alt4.aspmx.l.google.com 
alt3.aspmx.l.google.com 

См [ bash arrays ], [ command subsctitution ] и [ positional parameters ].

Вы предупреждены: Выход может быть только в одном формате. Хотя ($(..)) - это анти-шаблон, как указано в comment#1, для этого случая этого было бы достаточно.

+1

С помощью двойного цитирования подстановки команд вы всегда создаете массив с элементом _single_, содержащим _all lines_, что не является целью. Без двойного цитирования выходные строки неизменно подвергаются разбиению на слова и глобулизации, и даже если это происходит в этом случае, '($ (...))' не является, как правило, надежным способом считывания вывода команды в массив (если вы не установите '$ IFS' и отключите глобусы, что не стоит усилий). – mklement0

+0

@ mklement0: Спасибо за указатель. Я подумал об этом, но потом забыл взять двойные кавычки в спешке, чтобы опубликовать ответ :) Изменен сейчас – sjsam

+0

@ mklement0: Кроме того, я согласен со второй частью вашего комментария – sjsam

3

Попробуйте следующее:

convert2array() { 
    # Bash v4+ alternative: `readarray -t` instead of `IFS=$'\n' read -d '' -ra` 
    IFS=$'\n' read -d '' -ra "$1" <<<"$2" 
} 

mx=$(dig +short google.com mx | cut -d' ' -f 2 | sed 's/\.$//') 

convert2array mx_arr "$mx" 

printf '%s\n' "${mx_arr[@]}" 

А что вы пробовали:

  • $1 внутри convert2array не имя вашей входной переменной, $mx, но его Значение.
    Вы должны передать имя переменной, которую вы хотите объявить (возможно, после изменения имени ввода) явно, в качестве отдельного аргумента.

  • read по умолчанию считывает только 1-й строку ввода, в то время как вы передаете множественные линии.
    -d '' делает read чтения все линии, и IFS=$'\n' делает read читать каждую строку в целом.
    В Bash v4 +, используя встроенный readarray, IFS=$'\n' read -d '' -ra можно заменить на readarray -t.


оптимизированной версией вашей команды будет читать dig ... выходных линии непосредственно в массив, используя Баш v4 + readarray:

встроенной команду
readarray -t mx_arr < <(dig +short google.com mx | cut -d' ' -f 2 | sed 's/\.$//') 

Bash v3.x альтернативы :

IFS=$'\n' read -d '' -ra mx_arr < <(dig +short google.com mx | cut -d' ' -f 2 | sed 's/\.$//') 
1

Всего 1 обратите внимание на то, что пошло не так в вашей функции:

convert2array() { 
read -a $1_arr <<< $1 
} 

Здесь вы читаете в содержании $1, который является имя переменной, когда вы хотите прочитать содержимое самой переменной. Вы можете использовать окольные здесь:

convert2array() { 
    read -a $1_arr <<< ${!1} 
} 

Как уже отмечалось, есть более простые способы, чтобы получить выход в массивах.

0

При условии, что массив является только один-офф, для выходного контура только для чтения, POSIX оболочки может это сделать:

set -- `dig +short google.com mx` ; \ 
while [ "$2" ] ; do echo "${2%.*}" ; shift 2 ; done 

Выход:

alt2.aspmx.l.google.com 
alt3.aspmx.l.google.com 
alt4.aspmx.l.google.com 
alt1.aspmx.l.google.com 
aspmx.l.google.com 

Если потребности выходных далее суетиться, труба echo в любое другое, что нужно делать.


Примечание: Приведенный выше код содержит простой кладж, чтобы избежать sed и cut - вместо того, чтобы просто выход только четное число членов массива, а также использовать parameter expansion «Удалить Наименьший суффиксов Pattern», чтобы удалить, что ' «. в конце.