열이 2개만 있는 CSV 파일이 있습니다(하지만위치행) 및 항상 별표(*) 문자로 시작하고 세 개 이상의 열에 걸쳐 있을 수 있는 가끔 불규칙한 행이 있습니다. Linux 명령줄만 사용하면 예상되는 동작은 다음과 같습니다.
- 3개 이상의 연속된 데이터 행이 두 번째 열 값이 동일한 경우 가운데 행을 삭제합니다. 시작선과 끝선을 유지하세요.
- 별표로 시작하는 불규칙한 선 유지
예를 들어 다음을 포함하는 CSV가 있는 경우:
0,Apple
1,Apple
2,Apple
* Checkpoint
* Another checkpoint
3,Apple
4,Apple
5,Box
6,Box
7,Citrus
8,Box
9,Apple
10,Apple
11,Apple
12,Dove
13,Citrus
* Sudden checkpoint, * Leftover checkpoint note 1, * Leftover checkpoint note N
14,Citrus
15,Citrus
16,Citrus
17,Apple
18,Citrus
그러면 다음과 같아야 합니다.
0,Apple
* Checkpoint
* Another checkpoint
4,Apple
5,Box
6,Box
7,Citrus
8,Box
9,Apple
11,Apple
12,Dove
13,Citrus
* Sudden checkpoint, * Leftover checkpoint note 1, * Leftover checkpoint note N
16,Citrus
17,Apple
18,Citrus
위 예에서는 1~3행, 10행, 14~15행이 삭제되었습니다.
어떤 답변이라도 미리 감사드립니다.
건배
답변1
사용 awk
:
BEGIN { FS = "," }
/^[*]/ { print; next }
{
if (NR > 1 && $2 == word) {
tail = $0
++count
} else {
if (count) print tail
word = $2; count = 0
print
}
}
END { if (count) print tail }
스크립트 awk
는 무조건 로 시작하는 모든 줄을 인쇄합니다 *
. 행이 그러한 행이 아니고 두 번째 필드의 단어가 우리가 기억하는 단어인 경우 해당 레코드를 변수 tail
(동일한 단어가 포함된 일련의 레코드의 마지막 레코드와 같은 "꼬리")에 저장합니다. 필드).
두 번째 필드가 다음과 같은 경우아니요이전과 동일하고 tail 레코드를 인쇄합니다. 이전 실행의 레코드가 여러 개인 경우 새 단어를 기억하고 동일한 단어의 두 번째 필드에 현재 레코드(새 실행의 하나 이상의 레코드 중 첫 번째 레코드)를 인쇄합니다. ).
제공된 데이터에 대해 테스트하고 다음과 같다고 가정합니다.간단한 CSV(임베디드 구분 기호나 개행 문자 등이 없음을 의미):
$ awk -f script file
0,Apple
* Checkpoint
* Another checkpoint
4,Apple
5,Box
6,Box
7,Citrus
8,Box
9,Apple
11,Apple
12,Dove
13,Citrus
* Sudden checkpoint, * Leftover checkpoint note 1, * Leftover checkpoint note N
16,Citrus
17,Apple
18,Citrus
위와 유사하지만 사용밀러( mlr
), 이는 CSV를 지원하고 복잡한 인용 문자열이 포함된 CSV 레코드를 처리할 수 있습니다.
if (is_not_null(@word) && $2 == @word) {
@tail = $*;
false # omit this record for now
} else {
is_not_null(@tail) {
emit @tail # emit the tail record
}
@word = $2; @tail = null;
true # emit this record
}
end { is_not_null(@tail) { emit @tail } }
filter
awk
이는 위의 코드와 매우 유사한 논리를 사용하여 입력 데이터 세트의 레코드를 포함하거나 생략하는 Miller 하위 명령에 대한 표현식입니다 . Miller가 이 문자로 시작하는 줄을 탐색하도록 명령줄에서 use를 *
사용할 수 있습니다 . 입력을 헤더 없는 CSV로 처리하려면 with를 --pass-comments-with='*'
사용하세요 .--csv
-N
$ mlr --pass-comments-with='*' --csv -N filter -f script file
0,Apple
* Checkpoint
* Another checkpoint
4,Apple
5,Box
6,Box
7,Citrus
8,Box
9,Apple
11,Apple
12,Dove
13,Citrus
* Sudden checkpoint," * Leftover checkpoint note 1"," * Leftover checkpoint note N"
16,Citrus
17,Apple
18,Citrus