2017-02-20 6 views
0

Глядя, чтобы иметь возможность анализировать массив на основе переменной и принимать следующие 2 символаАнализировать массив на основе переменной и п-й символ

array=(7501 7302 8403 9904) 

если вар = 73, желаемого результата является 02
если переменная = 75, желаемого результата является 01
, если переменная = 84, желаемого результата является 03
, если переменная = 99, желаемого результата является 04

Извините, если это элементарный вопрос, но я пробовал варианты cut и grep и не могу найти решение.

Любая помощь очень ценится.

ответ

2

Вы можете использовать эту функцию поиска с помощью printf и awk:

srch() { 
    printf "%s\n" "${array[@]}" | awk -v s="$1" 'substr($1, 1, 2) == s{ 
    print substr($1, 3)}' ; 
} 

Затем используйте его как:

srch 75 
01 

srch 73 
02 

srch 84 
03 

srch 99 
04 
+0

Это, конечно, работает *, но это довольно значительная сумма затрат времени на просмотр, нет? –

+0

Это один из самых простых 'awk', который также использует поиск без регулярных выражений. Не сравнили это, но не должны быть плохими. – anubhava

+1

Хм.Если это действительно * есть * просто двузначные ключи, вы правы, что мы не можем иметь входные данные так долго, что разница между O (1) и O (n) на практике является такой большой; вероятно, будет придерживаться в пространстве, где главными драйверами являются затраты на запуск и подоболочку/трубопровод. OTOH, если этот поиск выполняется внутри жесткой петли (т. Е. По одному на строку ввода), мы можем добраться до места, где вызовы могут складываться, как раз из вышеупомянутых расходов с постоянным коэффициентом. –

2

Поскольку Баш массивы немногочисленны, даже в более старых версиях Баш, которые не имеют ассоциативные массивы (сопоставление произвольных строк как ключей), вы можете иметь регулярный массив, который имеет ключи только для числовых индексов, которые вы хотите сопоставить. Рассмотрим следующий код, который принимает ваш входной массив и генерирует выходной массив этой формы:

array=(7501 7302 8403 9904) 

replacements=()     # create an empty array to map source to dest 
for arg in "${array[@]}"; do  # for each entry in our array... 
    replacements[${arg:0:2}]=${arg:2} # map the first two characters to the remainder. 
done 

Это создаст массив, который выглядит как (если вы запускали declare -p replacements после кода выше сбросить описание replacements переменная):

# "declare -p replacements" will then print this description of the new array generated... 
# ...by the code given above: 
declare -a replacements='([73]="02" [75]="01" [84]="03" [99]="04")' 

Вы можете тривиальным искать любую запись в нем, как операции с постоянной времени, которая не требует внешних команд:

$ echo "${replacements[73]}" 
02 

... или перебирать ключи и соответствующие значения независимо друг от друга:

for key in "${!replacements[@]}"; do 
    value=${replacements[$key]} 
    echo "Key $key has value $value" 
done 

... который будет выделяющие:

Key 73 has value 02 
Key 75 has value 01 
Key 84 has value 03 
Key 99 has value 04 

Примечания/Ссылки:

  • Посмотреть the bash-hackers wiki on parameter expansion для понимания синтаксиса, используемого для среза элементов (${arg:0:2} и ${arg:2}).
  • См. BashFAQ #5 или the BashGuide on arrays для получения более подробной информации о синтаксисе, использованном выше.
+0

Хорошее решение, вопрос: что произойдет, если у вас есть повторяющиеся записи (например, [73] x 2)? –

+0

@ l'L'l, последний перезаписывает первое. Я не вижу ничего определенного в вопросе о том, что это поведение будет противоречить. –

+0

Да, не упоминалось - мне было просто любопытно ... –