한 줄에 6개의 값이 있는 타임스탬프가 있는 로그 파일이 있는데, 동일한 값이 있는 연속 줄을 제거하고(타임스탬프 무시) 각 반복 집합의 첫 번째 줄과 마지막 줄을 유지하여 데이터 양을 줄이고 싶습니다. bash 스크립트를 사용하는 것이 더 좋습니다. 마법 sed
이나 awk
명령 의 조합이어야 합니다 .
파일을 여러 번 구문 분석해야 하더라도 한 번에 3줄씩 읽고 중간 줄을 제거하는 것이 좋은 해결책입니다.
원본 파일:
1447790360 99999 99999 20.25 20.25 20.25 20.50
1447790362 20.25 20.25 20.25 20.25 20.25 20.50
1447790365 20.25 20.25 20.25 20.25 20.25 20.50
1447790368 20.25 20.25 20.25 20.25 20.25 20.50
1447790371 20.25 20.25 20.25 20.25 20.25 20.50
1447790374 20.25 20.25 20.25 20.25 20.25 20.50
1447790377 20.25 20.25 20.25 20.25 20.25 20.50
1447790380 20.25 20.25 20.25 20.25 20.25 20.50
1447790383 20.25 20.25 20.25 20.25 20.25 20.50
1447790386 20.25 20.25 20.25 20.25 20.25 20.50
1447790388 20.25 20.25 99999 99999 99999 99999
1447790389 99999 99999 20.25 20.25 20.25 20.50
1447790391 20.00 20.25 20.25 20.25 20.25 20.50
1447790394 20.25 20.25 20.25 20.25 20.25 20.50
1447790397 20.25 20.25 20.25 20.25 20.25 20.50
1447790400 20.25 20.25 20.25 20.25 20.25 20.50
원하는 결과:
1447790360 99999 99999 20.25 20.25 20.25 20.50
1447790362 20.25 20.25 20.25 20.25 20.25 20.50
1447790386 20.25 20.25 20.25 20.25 20.25 20.50
1447790388 20.25 20.25 99999 99999 99999 99999
1447790389 99999 99999 20.25 20.25 20.25 20.50
1447790391 20.00 20.25 20.25 20.25 20.25 20.50
1447790394 20.25 20.25 20.25 20.25 20.25 20.50
1447790400 20.25 20.25 20.25 20.25 20.25 20.50
답변1
uniq는 (일종의) 완벽한 도구입니다. 기본적으로 uniq에서는 컬렉션의 첫 번째 행을 유지/표시할 수 있지만 마지막 행은 유지/표시할 수 없습니다.
uniq에는 처음 몇 개의 필드를 건너뛸 수 있는 -f 플래그가 있습니다.
맨 유니크에서:
-f, --skip-fields=N
avoid comparing the first N fields
-s, --skip-chars=N
avoid comparing the first N characters
A field is a run of blanks (usually spaces and/or TABs), then non-blank characters. Fields are skipped before chars.
uniq -c를 사용하여 개수를 표시하고 uniq가 수행하는 작업을 확인하는 예:
-bash-4.2$ uniq -c -f 1 original_file
1 1447790360 99999 99999 20.25 20.25 20.25 20.50
9 1447790362 20.25 20.25 20.25 20.25 20.25 20.50
1 1447790388 20.25 20.25 99999 99999 99999 99999
1 1447790389 99999 99999 20.25 20.25 20.25 20.50
1 1447790391 20.00 20.25 20.25 20.25 20.25 20.50
3 1447790394 20.25 20.25 20.25 20.25 20.25 20.50
좋은. 원하는 것에 매우 가깝습니다. 그리고 그것은 쉽습니다. 그러나 그룹의 마지막 일치 행이 누락되었습니다. . . .
이 문제에 대해서는 uniq의 그룹화 옵션도 흥미롭습니다. . .
--group[=METHOD]
show all items, separating groups with an empty line METHOD={separate(default),prepend,append,both}
-D, --all-repeated[=METHOD]
print all duplicate lines groups can be delimited with an empty line METHOD={none(default),prepend,separate}
예를 들어 그룹별 uniq입니다. . .
-bash-4.2$ uniq --group=both -f 1 original_file
1447790360 99999 99999 20.25 20.25 20.25 20.50
1447790362 20.25 20.25 20.25 20.25 20.25 20.50
1447790365 20.25 20.25 20.25 20.25 20.25 20.50
1447790368 20.25 20.25 20.25 20.25 20.25 20.50
1447790371 20.25 20.25 20.25 20.25 20.25 20.50
1447790374 20.25 20.25 20.25 20.25 20.25 20.50
1447790377 20.25 20.25 20.25 20.25 20.25 20.50
1447790380 20.25 20.25 20.25 20.25 20.25 20.50
1447790383 20.25 20.25 20.25 20.25 20.25 20.50
1447790386 20.25 20.25 20.25 20.25 20.25 20.50
1447790388 20.25 20.25 99999 99999 99999 99999
1447790389 99999 99999 20.25 20.25 20.25 20.50
1447790391 20.00 20.25 20.25 20.25 20.25 20.50
1447790394 20.25 20.25 20.25 20.25 20.25 20.50
1447790397 20.25 20.25 20.25 20.25 20.25 20.50
1447790400 20.25 20.25 20.25 20.25 20.25 20.50
그런 다음 grep을 통해 각 빈 줄 앞과 뒤의 줄을 찾아 빈 줄을 제거합니다.
-bash-4.2$ uniq --group=both -f 1 original_file |grep -B1 -A1 ^$ |grep -Ev "^$|^--$"
1447790360 99999 99999 20.25 20.25 20.25 20.50
1447790362 20.25 20.25 20.25 20.25 20.25 20.50
1447790386 20.25 20.25 20.25 20.25 20.25 20.50
1447790388 20.25 20.25 99999 99999 99999 99999
1447790389 99999 99999 20.25 20.25 20.25 20.50
1447790391 20.00 20.25 20.25 20.25 20.25 20.50
1447790394 20.25 20.25 20.25 20.25 20.25 20.50
1447790400 20.25 20.25 20.25 20.25 20.25 20.50
다다다! 좋은.
답변2
awk
라이너 와 함께 제공 :
awk '{n=$2$3$4$5$6$7}l1!=n{if(p)print l0; print; p=0}l1==n{p=1}{l0=$0; l1=n}END{print}' file
요점은 여러 변수를 조작하는 것입니다. n
첫 번째 필드를 제외한 모든 필드를 현재 행에 저장하면 이전 행과 전체 이전 행이 l1
동일합니다. l0
이는 p
이전 줄이 인쇄되었는지 여부를 표시하는 플래그일 뿐입니다.
답변3
Perl이 구조에 옵니다:
perl -ne '($t, $r) = /([0-9]+\s+)(.*)/;
print "$pt$p\n$_" if $r ne $p;
$p = $r;
$pt = $t;
}{
print $t, $r' input-file \
| sort -nu | tail -n+2
-n
입력을 한 줄씩 읽습니다.$t
$r
"나머지"는 타임스탬프에 공백을 더한 것입니다 .$p
이전 브레이크이고$pt
이전 타임스탬프입니다.- 마지막 줄은 항상 인쇄됩니다.
Perl은 일부 라인을 두 번 인쇄하므로 sort -nu
중복된 내용은 제거해야 합니다. tail
첫 번째 빈 줄을 삭제합니다.
답변4
sed -e:t -e'$!{1N;N;s/\( .*\)\(\n[^ ]*\1\)\{2\}$/\1\2/;tt' -e'P;D;}' <in >out
...그거 작동해요. 이는 두 번째 공백으로 구분된 필드부터 시작하여 동일한 것으로 간주되는 일련의 3개 입력 라인에서 두 번째 입력 라인을 재귀적으로 대체합니다. 더 이상 그렇게 할 수 없을 때까지 대체하는 각 입력 라인을 대체하기 위해 다른 입력 라인을 계속해서 그릴 것입니다. 유사한 세 줄이 일치하지 않는 경우에만 P
버퍼의 첫 번째 줄을 인쇄한 후 삭제한 다음 D
나머지 두 줄과 다음 입력 줄로 다시 시도하기 위해 루프백합니다.
GNU 또는 BSD 사용 sed
:
sed -Ee:t -e'1N;$!N;s/( .*)(\n[^ ]*\1){2}$/\1\2/;tt' -eP\;D <in >out
1447790360 99999 99999 20.25 20.25 20.25 20.50
1447790362 20.25 20.25 20.25 20.25 20.25 20.50
1447790386 20.25 20.25 20.25 20.25 20.25 20.50
1447790388 20.25 20.25 99999 99999 99999 99999
1447790389 99999 99999 20.25 20.25 20.25 20.50
1447790391 20.00 20.25 20.25 20.25 20.25 20.50
1447790394 20.25 20.25 20.25 20.25 20.25 20.50
1447790400 20.25 20.25 20.25 20.25 20.25 20.50