100개의 행과 숫자 열이 포함된 CSV 테이블이 있습니다. 테이블의 일부 숫자가 포함된 1열 파일인 또 다른 목록이 있습니다. 목록에 없는 CSV의 모든 값을 제거하는 방법이 있나요?
이걸 목록 파일로 쓸 수 있을 줄 알았는데 grep -f
, 제거하고 싶은 값 중 일부가 유지하고 싶은 값과 같은 행에 있어서 고민 중입니다.
예를 들어
CSV 테이블:
11,12,13
11,10,12,13
목록 파일:
13
11
산출:
11,,13
11,,,,13
또는 대안적으로
11,13
11,13
답변1
다음 awk
절차에서는 CSV 필드에 선행 또는 후행 공백이 없다고 가정합니다.
awk 'BEGIN {FS=OFS=","}
NR==FNR{valid[$1];next}
{for (i=1;i<=NF;i++) {if (!($i in valid)) {$i=""}}} 1' validvalues.txt input.csv
validvalues.txt
유효한 값이 포함된 파일을 먼저 처리 한 다음 실제 CSV 파일을 처리합니다 .
BEGIN
섹션 에서 입력 및 출력에 대한 필드 구분 기호가 로 설정됩니다,
.- 첫 번째 파일( 파일별
NR
라인 카운터와 동일한 글로벌 라인FNR
카운터로 표시됨)을 처리할 때 허용되는 값을 배열의 인덱스로 기록하고valid
, 그렇지 않으면 다음 입력 라인으로 처리를 건너뜁니다. - 두 번째 파일을 처리할 때 모든 필드를 반복하고 필드 내용이 "배열 인덱스"의 일부인지 확인합니다
valid
. 그렇지 않은 경우 필드 값을 빈 필드로 설정합니다. 1
지금까지의 모든 수정 사항을 포함하여 현재 행의 겉보기에는 지저분해 보이는 인쇄입니다.
중요한 점은 ($i in valid)
테스트가 문자열 기반 비교이므로 유효한 값 파일의 열 항목이나 CSV 파일의 필드에 선행/후행 공백이 포함되어 있는 경우 비교를 위해서는 동일한 공백이 예상치 못한 동작이 발생할 수 있습니다.
@glenn jackman이 언급했듯이절차는 다음과 같이 단순화될 수 있습니다.
awk 'BEGIN {FS=OFS=","}
NR==FNR{valid[$1]=$1;next}
{for (i=1;i<=NF;i++) {$i=valid[$i]}} 1' validvalues.txt input.csv
여기서는 실제로 유효한 값을 "배열 값"으로도 등록합니다. 유효하지 않은 값은 에 항목이 없기 valid
때문에 valid[$i]
자동으로 빈 문자열로 평가되는 반면 유효한 값의 경우 값 자체를 반환한다는 아이디어입니다 .
그러나 "필드 값 자체"를 불필요하게 대체하고 더 많은 메모리를 필요로 하기 때문에 성능이 약간 느려지므로 "유효한 값" 파일이 큰 경우 문제가 될 수 있습니다.
답변2
다중 문자 RS 및 RT에 대한 GNU awk가 있는 경우:
$ awk -v RS='[,\n]' 'NR==FNR{a[$0]; next} {ORS=RT} $0 in a' list file.csv
11,13
11,13
답변3
원하지 않는 값의 파이프로 구분된 목록을 만들 수 있습니다.
list=$(<list.txt tr '\n' '|')
당신은 할 것 13|11|
.
그런 다음밀러검색 및 바꾸기
mlr --nidx --fs "," -S put 'for (k in $*) {if($[k]!=~"^('"$list"')$"){$[k] = gsub($[k], $[k], "")}}' input.csv
가지다
11,,13
11,,,13