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

Здесь меня бросают в глаза две проблемы:

  1. Вы не указали свои переменные в кавычках, поэтому оболочка потенциально искажает значения. Я дам вам альтернативное предложение для вашего скрипта, основанное на удалении пробелов .

  2. Вы обрабатываете XML с помощью регулярных выражений. Это будет работать сейчас, но имейте в виду, что в будущем это может сломаться, когда что-то неожиданное изменится.

Следующий код

#!/bin/bash

# ...

# Not even going to attempt to reduce this without seeing your XML
url=$(grep -E -m 1 -o "(.*)" costa_export.xml| sed -e 's,.*\([^<]*\).*,\1,g')

# Debug
echo "raw: $url" >&2

# Strip leading and trailing whitespace
url="${url#"${url%%[![:space:]]*}"}"   # remove leading whitespace
url="${url%"${url##*[![:space:]]}"}"   # remove trailing whitespace

# More debug
echo "now: $url" >&2

# Save the URL
echo -n "$url" > url.txt

# Retrieve the URL contents
wget -O price.zip "$url"

8
28.12.2018, 09:42
1 ответ

Индексы массива представляют собой либо целые числа, либо строки в кавычках в 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
}
16
27.01.2020, 20:10

Теги

Похожие вопросы