Создание единой таблицы из нескольких файлов

При получении SIGHUP nginx перезагрузит обновленную конфигурацию, проверит ее при открытии файлов журналов и чтении сертификатов SSL , затем корректно завершит рабочие процессы, полагаясь на предыдущую конфигурацию.

Если случится так, что nginx не может прочитать некоторые SSL-сертификаты, я продолжу работать, используя более старую конфигурацию. В противном случае он продолжит функционировать и обрабатывать запросы независимо от того, что вы сделали с вашими файлами конфигурации. Даже если они сломаны,ваши сайты будут по-прежнему открываться.

Итак, да, вам не нужно перезапускать nginx и рисковать отключением сервера более чем на несколько секунд, если вы хотите, чтобы nginx видел обновленные сертификаты. Этого должно быть достаточно:

sudo service nginx reload

В большинстве текущих дистрибутивов с systemd, используемым по умолчанию, вы также можете перезагрузить nginx с помощью следующей команды:

sudo systemctl reload nginx

1
13.12.2016, 17:08
3 ответа

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

awk 'BEGIN {
         RS = "(\r\n|\n\r|\r|\n)"
         FS = " *\t *"
         SUBSEP = ":"
     }
     FNR==1 {
         ++file
     }
     NF>=2 {
         if ($1 in keynum)
             key = keynum[$1]
         else {
             key = ++keys
             keynum[$1] = key
             keystr[key] = $1
         }
         value[key,file] = $2
     }
     END {
         files = file
         for (key = 1; key <= keys; key++) {
             printf "%s", keystr[key]
             for (file = 1; file <= files; file++)
                 printf "\t%s", value[key,file]
             printf "\n"
         }
     }' INPUT1 INPUT2 ... INPUTN

Правило BEGIN устанавливает в качестве разделителя записей любой тип новой строки, так что каждая строка является отдельной записью. Он также устанавливает разделитель полей на табуляцию, включая любые пробелы вокруг нее.

В awk все массивы ассоциативны и в основном одномерны.Многомерные массивы поддерживаются путем объединения индексов с подпунктом SUBSEP между ними. Здесь мы используем : в качестве разделителя, потому что используемые индексы являются положительными целыми числами. (При желании вы можете использовать множество других символов; например, табуляцию \ t .)

Правило FNR == 1 запускается в первой строке каждого входного файла. Мы увеличиваем переменную файл так, чтобы она составляла 1 для первого входного файла, 2 для второго и так далее.

Правило NF> = 2 срабатывает для всех записей как минимум с двумя полями. В данном случае это означает, что для каждой строки есть символ табуляции. Первое поле - это ключ , а второе поле - значение .

Переменная key является положительным целым числом, относящимся к уникальной строке ключа. (1 относится к первому уникальному ключу , 2 - ко второму и т. Д., Во всех входных файлах.)

Ассоциативный массив keynum сопоставляет строки ключей с номерами ключей ( ключ , положительные целые числа). keystr - это обратное отображение, отображающее номера ключей в строки ключей.

В правиле NF> = 2 , если первое поле уже является известным ключом, ищется его номер. В противном случае первое поле добавляется как новая уникальная строка ключа. Затем второе поле сохраняется в массиве значение .

Правило END срабатывает после обработки всех входных файлов.Массив value , логически двумерный массив, содержит нужные нам поля.

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

Внутренний цикл перебирает файл по каждому входному файлу в том порядке, в котором они были перечислены. Каждая итерация создает дополнительный столбец к текущей строке вывода. Каждая строка вывода содержит ровно на один столбец больше, чем указанное количество входных файлов. (Обратите внимание, что если входные файлы не указаны, awk читает со стандартного ввода, и это считается, как если бы это был один входной файл.)

Это определенно не самый простой способ добиться этого, но мне он нравится, потому что он надежный (принимает входные файлы, созданные в Unix, Linux, старых Mac, новых Mac, Windows - в основном везде, где используется ASCII-совместимый набор символов; кроме того, он не запутается, если некоторые входные файлы имеют только подмножество всех известные ключи), относительно легко понять, поддерживать и адаптировать к подобным случаям.


Если вы хотите запустить вышеуказанное как сценарий, сохраните следующее, например, paste.awk :

#!/usr/bin/awk -f
BEGIN {
    RS = "(\r\n|\n\r|\r|\n)"
    FS = " *\t *"
    SUBSEP = ":"
}
FNR==1 {
    ++file
}
NF>=2 {
    if ($1 in keynum)
        key = keynum[$1]
    else {
        key = ++keys
        keynum[$1] = key
        keystr[key] = $1
    }
    printf "key = %s, file = %s, value = %s\n", key, file, $2 >/dev/stderr
    value[key,file] = $2
}
END {
    files = file
    for (key = 1; key <= keys; key++) {
        printf "%s", keystr[key]
        for (file = 1; file <= files; file++)
            printf "\t%s", value[key,file]
        printf "\n"
    }
}

Если у вас есть input1 , содержащий

        a
A       5
C       4
D       2

и input2 , содержащий

        b
A       2
B       5
C       3

и input3 , содержащий

        c
B       4
C       4
D       2

], но со вторым символом в каждой строке Tab ; т.е. создано с использованием, например,

printf ' \ta\nA\t5\nC\t4\nD\t2\n' > input1
printf ' \tb\nA\t2\nB\t5\nC\t3\n' > input2
printf ' \tc\nB\t4\nC\t4\nD\t2\n' > input3

или, если вы скопируете и вставите текст выше в файлы, запустите sed -e 's | ^ \ (.\) * | \ 1 \ t | ' -i input1 input2 input3 , чтобы исправить их; затем выполнение

paste.awk input1 input2 input3

выводит

        a       b       c
A       5       2       
C       4       3       4
D       2               2
B               5       4

, за исключением того, что следующие подряд пробелы на самом деле являются вкладками . Как видите, программное обеспечение на этом сайте преобразует табуляции в пробелы.

Отредактировано для добавления: если вы хотите использовать какое-то предопределенное значение для отсутствующих записей,измените правило END на

END {
    files = file
    for (key = 1; key <= keys; key++) {
        printf "%s", keystr[key]
        for (file = 1; file <= files; file++)
            if ((key SUBSEP file) in value)
                printf "\t%s", value[key,file]
            else
                printf "\t%s", blank
        printf "\n"
    }
}

и установите переменную пустой , чтобы отразить желаемое значение. (Вы можете установить его из командной строки, используя ./ paste.awk -v blank = 0 input1 input2 input3 , либо изменить код awk и установить значение где-нибудь в BEGIN ] или начало правила END .)

2
27.01.2020, 23:14

join - это инструмент, который можно использовать, но его параметры немного неприятны:

join -t $'\t' -a1 -a2 -o 0,1.2,2.2     file1 file2 |
join -t $'\t' -a1 -a2 -o 0,1.2,1.3,2.2     - file3 |
sed 's/\t\(\t\|$\)/\t0\1/g'
    a   b   c
A   5   2   0
B   0   5   4
C   4   3   4
D   2   0   2

Сначала я использовал параметр -e , но это вызвало проблемы с строкой заголовка.

3
27.01.2020, 23:14

Вот версия GNU awk. Сначала я нахожу все ключевые значения, поэтому могу заполнить пустые значения нулями:

keys=$(cut -d $'\t' -f1 file{1,2,3} | sort -u | paste -sd,)
gawk -F'\t' -v keys="$keys" '
    BEGIN {
        n = split(keys,k,/,/)
        for (i=1; i<=n; i++) values[k[i]] = k[i]
    }
    {v[$1] = $2} 
    ENDFILE {
        for (key in values) 
            values[key] = values[key] FS (v[key] ? v[key] : 0)
        delete v
    } 
    END {
        for (key in values) print values[key]
    }
' file1 file2 file3 | sort -t $'\t' -k 1,1
1
27.01.2020, 23:14

Теги

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