이 헤더의 이름을 어떻게 지정해야 할지 모르겠지만 제가 얻은 것은 다음과 같습니다.
다음 텍스트가 포함된 파일:
[10:03:43] 10:03:35 22JUN22 ConUP CW1B1 T CW1B3 T CW1B5 T CW1B7 T
[10:03:44] CW2B1 T CW2B4 T CW2B5 T CW2B7 T
[10:03:44] CW3B1 T CW3B4 T CW3B5 T CW4B4 T
[10:03:44] CW4B8 T CW5B4 T CW5B8 T CW6B4 T
[10:03:44] CW6B8 T CW7B8 T CW8B4 T CW8B8 T
[10:03:44] CW9B4 T CW9B8 T CW10B4 T CW10B8 T
[10:03:44] CW11B4 T CW11B8 T CW12B4 T CW12B8 T
[10:04:16] 10:04:28 22JUN22 ConUP CW1B1 T CW1B3 T CW1B5 T CW1B7 T
[10:04:36] CW2B1 F CW2B3 F CW2B5 F CW2B7 F
[10:04:36] CW3B1 T CW3B4 T CW3B5 T CW4B4 T
[10:04:36] CW4B8 T CW5B4 T CW5B8 T CW6B4 T
[10:04:37] CW6B8 T CW7B8 T CW8B4 T CW8B8 T
[10:04:37] CW9B4 T CW9B8 T CW10B4 T CW10B8 T
[10:04:37] CW11B4 T CW11B8 T CW12B4 T CW12B8 T
그런 다음 실제 파일은 True 및 False 값의 변경 사항으로 채워집니다.
a에 True 항목이 있고 마지막 항목 이후 변경되지 않은 경우에는 해당 항목을 제거하고 값이 False로(또는 False에서 True로) 변경될 때만 유지하고 싶습니다.
아이디어는 문자열(예: CW1B1)의 첫 번째 항목을 찾은 다음 그 뒤에 오는 T 또는 F 값을 변수로 저장해야 한다는 것입니다. 그런 다음 다음에 나타나는 항목을 확인하고 T/F 값을 비교하십시오. 동일하면 잘라내기 또는 보내기를 사용하여 항목을 삭제하고 다음 항목을 찾으십시오. 값이 변경된 경우 무시하고 계속하십시오.
예상 출력:
[10:03:43] 10:03:35 22JUN22 ConUP CW1B1 T CW1B3 T CW1B5 T CW1B7 T
[10:03:44] CW2B1 T CW2B4 T CW2B5 T CW2B7 T
[10:03:44] CW3B1 T CW3B4 T CW3B5 T CW4B4 T
[10:03:44] CW4B8 T CW5B4 T CW5B8 T CW6B4 T
[10:03:44] CW6B8 T CW7B8 T CW8B4 T CW8B8 T
[10:03:44] CW9B4 T CW9B8 T CW10B4 T CW10B8 T
[10:03:44] CW11B4 T CW11B8 T CW12B4 T CW12B8 T
[10:04:16] 10:04:28 22JUN22 ConUP
[10:04:36] CW2B1 F CW2B3 F CW2B5 F CW2B7 F
[10:04:36]
[10:04:36]
[10:04:37]
[10:04:37]
[10:04:37]
어쩌면 더 좋은 방법이 있을 수도 있지만 여전히 프레임워크에 대한 도움이 필요하며 스크립트에 필요한 모든 가능한 변수를 생성할 수 있습니다.
답변1
이것은 아마도 당신이 원하는 것일 것입니다(테스트 가능한 예제 입력/출력이 제공되지 않으므로 테스트되지 않음).
awk '
{
for ( i=2; i<=NF; i++ ) {
if ( $i ~ /^[TF]$/ ) {
tag = $(i-1)
val = $i
if ( map[tag] == val ) {
$(i-1) = $i = ""
}
map[tag] = val
i++
}
}
$0 = $0
$1 = $1
print
}
' file
답변2
사용행복하다(이전 Perl_6)
raku -e 'my @a = words; @a.splice(1, *-128); @a.splice(64,*-62); \
@a.=rotor(9); @a = @a>>.[1..*-1].flat.rotor(2); my @b; for 0..27 -> $i { \
@a[$i] eq @a[$i+28] ?? @b.push(@a[$i]~"+") !! @b.push(@a[$i+28]~"x") }; \
.say for @b.rotor(4)>>.join("\t|\t");'
산출:
CW1B1 T+ | CW1B3 T+ | CW1B5 T+ | CW1B7 T+
CW2B1 Fx | CW2B3 Fx | CW2B5 Fx | CW2B7 Fx
CW3B1 T+ | CW3B4 T+ | CW3B5 T+ | CW4B4 T+
CW4B8 T+ | CW5B4 T+ | CW5B8 T+ | CW6B4 T+
CW6B8 T+ | CW7B8 T+ | CW8B4 T+ | CW8B8 T+
CW9B4 T+ | CW9B8 T+ | CW10B4 T+ | CW10B8 T+
CW11B4 T+ | CW11B8 T+ | CW12B4 T+ | CW12B8 T+
Raku를 사용하는 아이디어는 다음과 같습니다. 기본적으로 코드는 tail
로그 파일에서 실행할 수 있는 대시보드를 구축합니다. 입력을 받아 분해한 후 배열 words
에 할당합니다 . @a
행 1과 8에서 splice
추가 3개를 제거하는 데 사용됩니다 words
. 이제 몇 가지 재배열을 통해 1) 를 사용하여 9개 요소로 구성된 행을 다시 생성한 rotor(9)
다음 2) 첫 번째 열을 제거하고 나머지 8개 열을 2개 요소로 구성된 행으로 쌍을 이룰 수 있습니다(예: ) ("CW1B1", "T"), ("CW1B3", "T"), ("CW1B5", "T")...
.
이 시점부터 번호가 매겨진 28개의 요소가 있다는 것을 알 수 있습니다 0..27
. 28개 요소에 대한 반복을 사용하여 eq
및 사이의 문자열 동일성을 검색합니다 . "Test True False"인 Raku의 삼항 연산자는 True이면 첫 번째 문자열을 배열에 푸시하고(두 값이 모두 변경되지 않은 상태로 유지된다는 의미를 추가함), False이면 두 번째 문자를 푸시합니다. 문자열이 배열에 푸시됩니다( 값이 변경되었음을 나타내기 위해 a가 추가됩니다. 그런 다음 행(with)을 다시 행당 4쌍으로 다시 정렬하고 인쇄합니다.@a[$i]
@a[$i+28]
??
!!
@b
+
@b
x
rotor(4)
입력 예:
[10:03:43] 10:03:35 22JUN22 ConUP CW1B1 T CW1B3 T CW1B5 T CW1B7 T
[10:03:44] CW2B1 T CW2B4 T CW2B5 T CW2B7 T
[10:03:44] CW3B1 T CW3B4 T CW3B5 T CW4B4 T
[10:03:44] CW4B8 T CW5B4 T CW5B8 T CW6B4 T
[10:03:44] CW6B8 T CW7B8 T CW8B4 T CW8B8 T
[10:03:44] CW9B4 T CW9B8 T CW10B4 T CW10B8 T
[10:03:44] CW11B4 T CW11B8 T CW12B4 T CW12B8 T
[10:04:16] 10:04:28 22JUN22 ConUP CW1B1 T CW1B3 T CW1B5 T CW1B7 T
[10:04:36] CW2B1 F CW2B3 F CW2B5 F CW2B7 F
[10:04:36] CW3B1 T CW3B4 T CW3B5 T CW4B4 T
[10:04:36] CW4B8 T CW5B4 T CW5B8 T CW6B4 T
[10:04:37] CW6B8 T CW7B8 T CW8B4 T CW8B8 T
[10:04:37] CW9B4 T CW9B8 T CW10B4 T CW10B8 T
[10:04:37] CW11B4 T CW11B8 T CW12B4 T CW12B8 T
https://stackoverflow.com/questions/3416467/how-to-tail-f-the-latest-log-file-with-a-given-pattern
https://docs.raku.org/routine/splice
https://docs.raku.org/언어/operators#index-entry-operator_ternary
https://raku.org
답변3
다음 Perl 스크립트는 각 입력 줄에서 중복된 변수 값을 제거합니다. 이전에 본 적이 없거나 마지막으로 본 이후 변경된 변수만 출력에 포함됩니다. 빈 줄(즉, 새 변수나 변경된 변수가 없는 줄)은 인쇄되지 않습니다.
$ cat remove-dupes.pl
#!/usr/bin/perl
use strict;
# %vars is a hash (associative array) to store last-seen T/F values
# for the "variables". This is global in scope, i.e. defined here
# outside of the main loop because its keys & values need to be
# remembered across lines.
my %vars;
# read in and process each input line
while(<>) {
chomp; # remove newline character at end of line
# @out is an array to hold "VAR [TF]" values that we either
# haven't seen before or have changed since last time we saw
# them. i.e. the values we want to output. It needs to be
# reset to empty every time we read a line.
my @out = ();
# extract the first word (i.e. "ConUp") from input line
# by deleting all "VAR [TF]" strings from the line
my $first_word = $_;
$first_word =~ s/ ?\w+\s+[TF]//g;
# add it to @out if it isn't empty
push @out, $first_word if $first_word;
# Iterate over each "VAR [TF]" string in the line. Split
# it into the key (variable name) and value (T or F).
# If it's new or changed then add it to @out and
# remember its current value in %vars
while (/ ?\b(\w+ [TF])\b/g) {
my ($key,$val) = split / /, $1;
next if ($vars{$key} eq $val);
push @out, $1;
$vars{$key} = $val;
};
# join (with spaces) and print @out if it isn't empty.
if (@out) {print join(" ",@out), "\n"};
}
참고: 줄에 "VAR[TF]"가 아닌 다른 문자열이 있으면 출력에서 해당 줄의 시작 부분으로 이동됩니다. 이는 버그로 간주될 수도 있고 그렇지 않을 수도 있습니다. 샘플 데이터의 유일한 인스턴스는 첫 번째 줄 시작 부분에 있는 "ConUp"이므로 필요에 따라 작동합니다. 변수를 호출하면 안 되지만 $first_word
이 방법이 더 좋습니다.$anything_that_doesnt_match_a_boolean_variable_pattern
입력 파일에는 제거해야 할 중복 변수 값이 포함되어 있지 않으므로 해당 값이 포함된 파일을 생성했습니다(그리고 변경될 일부 변수 인스턴스를 추가했습니다).
$ cat file2.txt
ConUp CW1B1 T CW1B2 T CW1B3 F CW1B4 F
CW2B1 T CW2B2 F CW2B3 F CW2B4 T
CW2B1 F CW2B2 F CW2B3 F CW2B4 T
CW2B1 F CW2B2 F CW2B3 F CW2B4 T
CW2B1 T CW2B2 F CW2B3 F CW2B4 T
CW2B1 F CW2B2 F CW2B3 T CW2B4 T
예제 출력:
$ ./remove-dupes.pl file2.txt
ConUp CW1B1 T CW1B2 T CW1B3 F CW1B4 F
CW2B1 T CW2B2 F CW2B3 F CW2B4 T
CW2B1 F
CW2B1 T
CW2B1 F CW2B3 T
업데이트된 버전:
이 버전은 각 줄의 처음 34자를 "첫 번째 단어"로 추출합니다. 이는 sprintf()
각 요소를 @out
10자 너비 문자열로 형식화하는 데 사용되며 출력에서 후행 공백을 제거합니다. \s*
또한 \s+
단일 공백 대신 합계를 사용하여 공백 문자를 일치시키거나 분할합니다. 원본 스크립트의 설명이 여전히 적용되므로(사소한 변경 사항 포함) 간결성을 위해 설명을 제거했습니다.
$ cat remove-dupes2.pl
#!/usr/bin/perl
use strict;
my %vars;
while(<>) {
chomp;
my @out = ();
my $first_word;
($first_word = $_) =~ s/\b\w+\s+[TF]//g;
$first_word =~ s/^(.{34})\s+$/$1 /;
push @out, $first_word if $first_word;
while (/\s*\b(\w+\s+[TF])\b/g) {
my ($key,$val) = split /\s+/, $1;
next if ($vars{$key} eq $val);
push @out, sprintf("%-10s",$1);
$vars{$key} = $val;
};
my $out = join(" ",@out);
$out =~ s/\s+$//; # remove trailing spaces
print "$out\n";
}
새로운 입력 데이터를 사용한 출력 예( input.txt
). 아직은 아니야정확히예제 출력과 동일하지만 여전히 약간의 공백 차이가 있지만 출력은 위의 원본 스크립트 출력보다 훨씬 가깝습니다.
$ ./remove-dupes2.pl input.txt
[10:03:43] 10:03:35 22JUN22 ConUP CW1B1 T CW1B3 T CW1B5 T CW1B7 T
[10:03:44] CW2B1 T CW2B4 T CW2B5 T CW2B7 T
[10:03:44] CW3B1 T CW3B4 T CW3B5 T CW4B4 T
[10:03:44] CW4B8 T CW5B4 T CW5B8 T CW6B4 T
[10:03:44] CW6B8 T CW7B8 T CW8B4 T CW8B8 T
[10:03:44] CW9B4 T CW9B8 T CW10B4 T CW10B8 T
[10:03:44] CW11B4 T CW11B8 T CW12B4 T CW12B8 T
[10:04:16] 10:04:28 22JUN22 ConUP
[10:04:36] CW2B1 F CW2B3 F CW2B5 F CW2B7 F
[10:04:36]
[10:04:36]
[10:04:37]
[10:04:37]
[10:04:37]
[HH:MM::SS]
그런데, 거의 빈 줄(포함된 줄만)을 인쇄하고 싶지 않다면 print "$out\n";
줄을 print "$out\n" unless ($out =~ /^\[[^]]\]\s*$/);
.
유일한 차이점을 확인 하려면 diff
공백( output.txt
예제 출력)입니다.
$ ./remove-dupes2.pl input.txt > out.txt
$ diff --ignore-space-change -u output.txt out.txt
$