Похоже, если мы используем необязательный двоеточие :
, за которым следуют как минимум два пробела в качестве FS (FS = ":? *"
), большинство основных полей, используемых в этой задаче, можно изолировать без проблем с дополнительными пробелами:
$ cat t20.awk
BEGIN { FS=":? *"; OFS = ", "; SEP = "; "; }
# if $2 is "Type", append $3 to T
$2 == "Type" { T = (T ? T SEP : "") $3;}
# if $2 is "Retention Level", append sub-string in parenthesis to L
$2 == "Retention Level" && match($0, /\(.*?\)/) {
L = (L ? L SEP : "") substr($0, RSTART+1, RLENGTH-2)
}
# in Daily window block, skip all line without " --> "
# use an associative array "a" to make sure unique time range
/Daily Windows:/,/^\s*$/ {
if (!/ --> /) next
key = $3 " --> " $6
if (!a[key]++) S = (S ? S SEP : "") key
}
END { print T, L, S }
Примечание:
в S = (S ? S SEP : "") key
, тернарный (S ? S SEP : "")
должен избегать начального SEP при объединении строк, аналогично тому, как это происходит при объединении T
, L
.
в substr($0, RSTART+1, RLENGTH-2)
, используя RSTART+1
для удаления начального (
и RLENGTH-2
для удаления двух скобок
Запустите код:
$ awk -f t20.awk file.txt
#Full Backup; Full Backup; Differential Incremental Backup, 3 months; 1 month; 3 weeks, 00:00:00 --> 07:00:00; 00:00:00 --> 10:00:00; 01:00:00 --> 16:00:00
Обновление:
Основываясь на вашем описании в комментариях, я внес следующие коррективы в код части Daily Windows
:
dw_on == 1
и соответствующие шаблону / --> /
должны быть проверены на S
. этот флаг будет сброшен на 0
при обнаружении следующей ПУСТОЙ строки /^\s*$/
Daily Windows
Уникальность поддерживается хэшем (ассоциативным массивом)и , который будет сбрасываться в начале каждого блока Daily Windows
. Ключ этого хеша — key = $3 " --> " $6
, это окно, которое вы хотите получить. синтаксис:if (!a[key]++) S = (S ? S SEP : "") key
такой же, как
if (!a[key]) {
a[key] = a[key] + 1
S = (S ? S SEP : "") key
}
поэтому, только если ключ не виден до (a[key]="" ), можно key
добавить к S
, второй раз, когда тот же ключ обрабатывается, он уже иметь a[key]==1
и пропустить указанный выше блок кода. Это один из распространенных в awk
способов проверки уникальности.
$ cat t20.1.awk
BEGIN { FS=":? *"; OFS = ", "; SEP = "; "; }
# if $2 is "Type", append $3 to T
$2 == "Type" { T = (T ? T SEP : "") $3;}
# if $2 is "Retention Level", append sub-string in parenthesis to L
$2 == "Retention Level" && match($0, /\(.*?\)/) {
L = (L ? L SEP : "") substr($0, RSTART+1, RLENGTH-2)
}
/Daily Windows:/ {
# turn on the dw_on flag and reset cnt_DW (number of DW entries in a section)
dw_on = 1; cnt_DW=0;
# reset the hash 'a' for uniqueness check
# if you need the uniqueness across all Schedules, then comment it out
delete a;
next;
}
# if dw_on flag is true, i.e. "dw_on == 1"
dw_on {
# match " --> ", then increase cnt_DW, check the unique window
# and then append qualified entry to "S"
if (/ --> /) {
cnt_DW++
key = $3 " --> " $6
if (!a[key]++) S = (S ? S SEP : "") key
# else if EMPTY line, reset dw_on flag, if cnt_DW is 0, append "No Window" to S
} else if (/^\s*$/) {
dw_on = 0;
if (!cnt_DW) S = (S ? S SEP : "") "No Window"
}
}
END {
# last Schedule section does not have a EMPTY line, so we will need
# to check up cnt_DW in the last Schedule section in "END" block
if(dw_on && !cnt_DW) S = (S ? S SEP : "") "No Window";
# print the result.
print T, L, S
}
Я внес следующие небольшие изменения в ваши исходные данные, чтобы протестировать приведенный выше код:
Daily Windows
во 2-м разделе Schedule
Friday 00:00:00 --> Friday 07:00:00
в первом Приложении на Friday 01:00:00 --> Friday 16:00:00
, что совпадает с разделом 3-го Приложения. Итак, теперь в 1-м Расписании есть 2 уникальных окна, во 2-м Расписании нет окна, в 3-м Расписании есть 1 уникальное окно, такое же, как и в 1-м Расписании.
Запустите обновленный код с указанными выше данными, вы получите:
awk -f t20.1.awk file.txt
#Full Backup; Full Backup; Differential Incremental Backup, 3 months; 1 month; 3 weeks, 00:00:00 --> 07:00:00; 01:00:00 --> 16:00:00; No Window; 01:00:00 --> 16:00:00
Обратите внимание, что их два 01:00:00 --> 16:00:00
, потому что они находятся в разных расписаниях. Если вы хотите удалить последний 01:00:00 --> 16:00:00
, закомментируйте строку delete a
, как показано в коде, вы получите следующий результат:
#Full Backup; Full Backup; Differential Incremental Backup, 3 months; 1 month; 3 weeks, 00:00:00 --> 07:00:00; 01:00:00 --> 16:00:00; No Window
Простым методом может быть создание сценария Bash, который запускает их все. В приведенном ниже примере сценария, написанном для двух соединений, если вы назовете его tunnel
и chmod +x tunnel
, вы можете использовать
tunnel start
чтобы запустить их (идемпотентно )и
tunnel stop
, чтобы очистить их.
#!/bin/bash
C1="localhost:8866:127.0.0.1:3478 host1"
C2="localhost:8867:127.0.0.1:3478 host2"
pkill -f "$C1"
pkill -f "$C2"
if [ "$1" = stop ]; then exit 0; fi
sleep 3 # give some time for them to exit, if applicable
nohup ssh -N -L $C1 &> /dev/null &
nohup ssh -N -L $C2 &> /dev/null &
Другим методом может быть использование autossh
, чтобы поддерживать их работу по отдельности и, возможно, организовать их запуск при запуске системы.
Наконец, вы можете давать символические имена портам в /etc/services, хотя тогда мы начинаем создавать некоторую путаницу в конфигурации вашей системы. Вы можете предпочесть, чтобы порты находились в зарезервированном диапазоне (< 1024 ), что требует привилегий root.