awk/sed를 사용하여 csv를 필터링하여 특정 열(예: 열 1)의 값을 잘라내어 마지막 8자를 유지하고 시작 부분을 와일드카드로 바꾸는 방법을 찾으려고 합니다. 열이 NULL과 같지 않습니다. 예를 들어 열 3과 5
예시 데이터:
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,DATA,DATA,DATA,DATA
될 것입니다:
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*.filename2.exe,NULL,DATA,DATA,DATA,DATA
나는 일련의 파이핑을 사용하여 rev
이 스크립트를 작성했는데 매우 비효율적이며 많은 데이터로 작업하고 스크립트에 몇 시간이 걸리기 때문에 더 고급 / 필터를 cut
배우고 있습니다 .awk
sed
답변1
awk -v c=8 'BEGIN{ FS=OFS="," }
$3!="NULL" && $5!="NULL"{ $1=(length($1)>c?"*"substr($1,length($1)-c+1):$1) }1' infile
여기서는 c=#
열 #1의 길이가 8자를 초과하는 경우에만 "*"를 추가하고(유지할 문자 수를 변경할 수 있음), 그렇지 않으면 열 #1을 변경하지 않고 인쇄합니다.
답변2
펄 사용:
- 첫 번째 필드의 모든 항목을
_
논리 AND( ) 문자 까지 바꿉니다. 즉, 둘 다 "NULL"이 될 수 없습니다.&&
$ perl -F, -pe 's/^.*?_/*/ if ($F[2] ne "NULL" && $F[4] ne "NULL")' input.csv
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*filename2.exe,NULL,DATA,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,NULL,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,DATA,DATA,NULL,DATA
이는 Perl의 "탐욕적이지 않은" ?
수량자를 사용하여 .*
첫 번째(아마도 유일한) 밑줄 문자와만 일치합니다.
_
첫 번째 필드의 모든 항목을 논리 OR( ) 문자 까지 바꿉니다||
. 즉, 둘 다 "NULL"이 아니어야 합니다.
$ perl -F, -pe 's/^.*?_/*/ if ($F[2] ne "NULL" || $F[4] ne "NULL")' input.csv
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*filename2.exe,NULL,DATA,DATA,DATA,DATA
*filename2.exe,NULL,NULL,DATA,DATA,DATA
*filename2.exe,NULL,DATA,DATA,NULL,DATA
- 첫 번째 필드인 논리 AND의 마지막 8자를 제외한 모든 문자를 바꿉니다.
$ perl -F, -pe 's/^.*?(.{8}),/*$1,/ if ($F[2] ne "NULL" && $F[4] ne "NULL")' input.csv
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*ame2.exe,NULL,DATA,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,NULL,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,DATA,DATA,NULL,DATA
이는 캡처 그룹을 사용하여 (.{8})
첫 번째 필드의 마지막 8자를 추출하고 이를 사용하여 문자열( $1
)을 대체합니다.
- 첫 번째 필드(논리적 OR)의 마지막 8자를 제외한 모든 문자를 바꿉니다.
$ perl -F, -pe 's/^.*?(.{8}),/*$1,/ if ($F[2] ne "NULL" || $F[4] ne "NULL")' input.csv
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*ame2.exe,NULL,DATA,DATA,DATA,DATA
*ame2.exe,NULL,NULL,DATA,DATA,DATA
*ame2.exe,NULL,DATA,DATA,NULL,DATA
- 마지막 8자를 제외한 모든 문자 바꾸기기본 이름파일 이름의 일부(예: "확장자" 앞), 논리적 AND.
$ perl -F, -pe 's/^.*?(.{8})\./*$1./ if ($F[2] ne "NULL" && $F[4] ne "NULL")' input.csv
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*ilename2.exe,NULL,DATA,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,NULL,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,DATA,DATA,NULL,DATA
참고: 파일 이름 "확장자"는 Unix 및 Linux 파일 시스템에서 그다지 중요하지 않습니다. 또한 고대 MS-DOS FAT 파일 시스템처럼 3자로 제한되지 않고 여러 문자를 가질 수 있습니다. 최신 Windows 파일 시스템에서도 마찬가지입니다. 파일 이름에 .
여러 문자가 포함되어 있으면 이 버전은 예상대로 작동하지 않습니다.
- 이제 논리적 OR 버전이 분명해졌습니다.
참고: Perl 배열은 1이 아닌 0에서 시작합니다. 이것이 세 번째 필드가 에 있고 $F[2]
다섯 번째 필드가 에 있는 이유입니다 $F[4]
.
또한 AND와 OR 사용의 차이점을 보여주기 위해 예제 입력에 두 줄을 추가했습니다.
$ cat input.csv
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,DATA,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,NULL,DATA,DATA,DATA
asvasihtiqsafsoithqwtoihwoi_filename2.exe,NULL,DATA,DATA,NULL,DATA
입력의 세 번째 및 네 번째 라인은 두 번째 라인과 동일합니다. 단, 라인 3에서 필드 3의 "DATA"가 "NULL"로 변경되었고 라인 4에서 필드 5의 "DATA"가 변경되었습니다. "잘못되었습니다.
답변3
#!/usr/bin/python
import re
k=open('filepath','r')
for i in k:
kospl=i.strip().split(',')
if (kospl[2] != "NULL" and kospl[4] != "NULL" and kospl[0] >8):
lk=len(kospl[0])-13
k="*."+kospl[0][lk:]+","
print k+",".join(kospl[1:])
else:
print i.strip()
~
산출
1597012957a0dg9a0t593qa_filename1.exe,NULL,NULL,DATA,NULL,DATA
*.filename2.exe,NULL,DATA,DATA,DATA,DATA