다음 입력 파일이 있습니다.
Policy Name: KE15-LOCALHOST-APP-RADIX-DAILY
Policy Type: Standard
Active: yes
Include: /appussd
/home/ussd2ke
/var/log
/etc
/usr
Schedule: Montlhy_Full
Type: Full Backup
PFI Recovery: 0
Maximum MPX: 16
Retention Level: 5 (3 months)
Daily Windows:
Sunday 00:00:00 --> Sunday 07:00:00
Monday 00:00:00 --> Monday 07:00:00
Tuesday 00:00:00 --> Tuesday 07:00:00
Wednesday 00:00:00 --> Wednesday 07:00:00
Thursday 00:00:00 --> Thursday 07:00:00
Friday 00:00:00 --> Friday 07:00:00
Saturday 00:00:00 --> Saturday 07:00:00
Schedule: Weekly_Full
Type: Full Backup
PFI Recovery: 0
Maximum MPX: 16
Retention Level: 3 (1 month)
Daily Windows:
Wednesday 00:00:00 --> Wednesday 10:00:00
Schedule: Daily_Inc
Type: Differential Incremental Backup
PFI Recovery: 0
Maximum MPX: 16
Retention Level: 2 (3 weeks)
Daily Windows:
Sunday 01:00:00 --> Sunday 16:00:00
Monday 01:00:00 --> Monday 16:00:00
Tuesday 01:00:00 --> Tuesday 16:00:00
Wednesday 01:00:00 --> Wednesday 16:00:00
Thursday 01:00:00 --> Thursday 16:00:00
Friday 01:00:00 --> Friday 16:00:00
Saturday 01:00:00 --> Saturday 16:00:00
이제 쉼표와 ;로 구분된 (계획 아래), 보존 수준 및 일일 창 등 다양한 유형 쌍이 필요합니다. 여러 항목의 경우.
내가 시도한 명령은 다음과 같습니다. 문제는 일일 창에 있었습니다. 중간에 데이터를 가져와 일일 창 행을 제거할 수 있었습니다. 이제 요일 이름을 제거하고 고유한 기간만 원합니다.
awk '
BEGIN { SEP = "" }
$1 == "Type:" { $1 = ""; T = T SEP $0 }
$1 == "Retention" && $2 == "Level:" {
sub(/^.*\(/," ")
sub(/\).*/,"")
L = L SEP $0
if (SEP == "") {
SEP = ";"
}
}
/Daily Windows:/,/^$/ {
sub(/^.*Daily.*/,"")
sub(/^[^A-Z][a-z]+y$/,"")
S = S SEP $0}
END {
sub(/^ */,"",T)
print T "," L "," S
}'
출력은 다음과 같습니다.
Full Backup; Full Backup; Differential Incremental Backup, 3 months; 1 month; 3 weeks,;; Sunday 00:00:00 --> Sunday 07:00:00; Monday 00:00:00 --> Monday 07:00:00; Tuesday 00:00:00 --> Tuesday 07:00:00; Wednesday 00:00:00 --> Wednesday 07:00:00; Thursday 00:00:00 --> Thursday 07:00:00; Friday 00:00:00 --> Friday 07:00:00; Saturday 00:00:00 --> Saturday 07:00:00;;; Wednesday 00:00:00 --> Wednesday 10:00:00;;; Sunday 01:00:00 --> Sunday 16:00:00; Monday 01:00:00 --> Monday 16:00:00; Tuesday 01:00:00 --> Tuesday 16:00:00; Wednesday 01:00:00 --> Wednesday 16:00:00; Thursday 01:00:00 --> Thursday 16:00:00; Friday 01:00:00 --> Friday 16:00:00; Saturday 01:00:00 --> Saturday 16:00:00
그러나 원하는 출력은 다음과 같습니다.
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
답변1
:
선택적 콜론 과 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 }
노트:
에서는 연결 의 경우 와 유사하게 문자열을 연결할 때 선행 SEP를 피하기 위해
S = (S ? S SEP : "") key
트리플을(S ? S 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시작과 끝을 식별하기 위해일일 창막혔습니다.
dw_on == 1
이 패턴을 갖고 일치하는 모든 행을 확인해야 합니다. 다음 빈 줄이 감지될 때마다 이 플래그는 다음으로 재설정됩니다./ --> /
S
0
/^\s*$/
- 변수를 추가했습니다cnt_DW수량을 계산하다일일 창각 일정의 항목입니다. 이는
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
에 a를 추가 할 수 있습니다 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
Schedule
Part II에서 별도의 항목을 삭제했습니다 .Friday 00:00:00 --> Friday 07:00:00
첫 번째 일정의 행을Friday 01:00:00 --> Friday 16:00:00
세 번째 일정 섹션의 동일한 행으로 바꿉니다.
따라서 이제 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
답변2
다음을 통해 모든 작업을 수행할 수 있습니다 awk
.
awk -F'(: *|[)(])' '
/^ *Type/ { type=type==""?$2 : type ";" $2 }
/^ *Retention/{ Retention=Retention==""?$3 : Retention ";" $3}
/^ *Wednesday/{ gsub(/ +Wednesday/,"",$0); day=day==""?$0 : day ";" $0}
END{ print type, Retention, day }' OFS=, infile
/ ... /
필드 값을 보다 정확하게 일치시키려면 기준 섹션을 조정해야 할 수도 있습니다 .
출력은 예상한 대로입니다.