Ссылки на элементы массива по строкам и инициализация массивов в awk

8
#!/usr/bin/env bash
awk '
  BEGIN {
    arr[A]=1;
    arr[B]=1;
    arr[C]=1;
    arr[E]=1;
    arr[J]=8;
    arr[Q]=10;
    print arr[J]
  }'

Приведенная выше команда выводит последнее установленное значение для arr['subscript'], в данном случае 10это значение arr[Q]непосредственно перед, printа не 8значение arr[J].

Кроме того, как и в приведенном выше сценарии, я не хочу присваивать значения arr['A'], arr['B'], arr['C'] and arr['E'], имеющие одинаковое значение, по 1одной строке за раз, а скорее передать массив индексов в качестве одного из параметров и общее значение в качестве другого параметра в функцию, которая обрабатывает логика присвоения им значения.

HarshvardhanSharma
источник

Ответы:

16

Индексы массива представляют собой целые числа или строки в кавычках awk. Здесь вы используете переменные, которые еще не были инициализированы. Поэтому их значения пусты.

Вы получаете последнее значение, назначенное массиву, потому что каждое назначение перезаписывает предыдущее значение. Использование print arr[""]также 10вернет вас .

Вместо этого используйте строки, как в arr["A"]=1.

Для вашей последней проблемы: Нет реальной возможности инициализировать awkмассив из командной строки, но вы можете передать «закодированное» значение, которое вы «декодируете» в своем BEGINблоке (например), чтобы извлечь ключи и значения для массива.

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

awk -v vals="A=1:B=1:C=1:E=1:J=8:Q=10" '
    BEGIN {
        n = split(vals, v, ":")
        for (i = 1; i <= n; ++i) {
            split(v[i], a, "=")
            arr[a[1]] = a[2]
        }

        print arr["J"]
    }'

Используя отдельные ключи и значения:

awk -v keys="A:B:C:E:J:Q" -v vals="1:1:1:1:8:10" '
    BEGIN {
        nk = split(keys, k, ":")
        nv = split(vals, v, ":")

        if (nk != nv) exit 1

        for (i = 1; i <= nk; ++i)
            arr[k[i]] = v[i]

        print arr["J"]
    }'

Это довольно ограниченный способ передачи «массива» awk, но он работает для простых значений, которые полностью контролируются. Примеры будут разбиты для любых данных, которые встраивают двоеточия (и знаки равенства для 1-го примера) в фактические данные.

Подобная передача данных также означает, что обратные слеши в данных должны обрабатываться особым образом ( \nбудет новой строкой \n, поэтому для передачи двухсимвольной строки вам придется использовать "\\\n"или '\\n').

Также связано:


Кроме того, вы можете написать «чистый awkсценарий», например так:

#!/usr/bin/awk -f

BEGIN { 
   # some initialisations
}

some_expression { some code }

END {
    # more here
}
Кусалананда
источник