세 번째 또는 n 번째 문자 발생 후 CSV의 특정 열에 있는 데이터를 자르려고 하는 필터로 인해 어려움을 겪고 있습니다 \
.
내 데이터는 다음과 같습니다.
data,data,c:\path1\folder2\folder3\folder4\...,data,data,data
data,data,c:\path1\folder2\folder3\folder4\...,data,data,data
data,data,c:\path1\folder2\folder3\folder4\...,data,data,data
data,data,c:\path1\folder2\folder3\folder4\...,data,data,data
필터가 다음을 생성하기를 원합니다.
data,data,c:\path1\folder2\folder3\,data,data,data
세 번째 열에는 하나의 폴더에서 여러 폴더까지 어디에나 있을 수 있는 파일 경로가 포함됩니다. 최대 3개의 폴더를 갖고 싶습니다.
다른 나머지 열을 삭제하고 싶지 않고 파일을 제자리에서 편집하고 싶습니다.
awk
나는 , sed
, cut
명령을 명령문 cut -f1-4 -d '\'
으로 결합하려고 노력했지만 awk
평생 동안 그것을 작동시킬 수는 없습니다.
답변1
GNU awk를 사용하여 gensub()를 실행합니다:
$ awk -v n=3 'BEGIN{FS=OFS=","} {$3=gensub("(([^\\\\]*\\\\){"n+1"}).*","\\1",1,$3)} 1' file
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
또는 awk를 사용하십시오.
$ awk -v n=3 'BEGIN{FS=OFS=","} match($3,"(([^\\\\]*\\\\){"n+1"})"){$3=substr($3,1,RLENGTH)} 1' file
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
답변2
sed
4개의 백슬래시로 구분된 문자열이 포함된 다른 이전 필드가 없다고 가정하고 를 사용합니다 .
$ sed 's/\(\([^,\]\{1,\}[\]\)\{4\}\)[^,]*/\1/' file
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
또는 확장 정규식을 사용하여
$ sed -E 's/(([^,\]+[\]){4})[^,]*/\1/' file
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
data,data,c:\path1\folder2\folder3\,data,data,data
여기에 사용된 표현 sed
은 대체 표현이며, 대체되는 텍스트는 이와 일치하는 모든 것입니다 (([^,\]+[\]){4})[^,]*
. 이 정규식은 비어 있지 않은 백슬래시로 구분된 4개의 문자열( ([^,\]+[\]){4}
)과 일치하고 캡처합니다. 이는 대체 문자열에서 재사용하기 위해 캡처되지만 [^,]*
다음 쉼표를 포함한 모든 항목(후행 일치 항목이 무엇이든)은 삭제됩니다.
대체 텍스트는 \1
삽입되는 4자리 백슬래시로 구분된 문자열입니다.
cut
분명히 and 를 사용하여 이 작업을 수행 할 수도 있지만 paste
다음 명령은 파일을 읽기 위해 파이프됩니다.세 번, 세 번째 필드의 경로 이름에서 마지막 백슬래시를 제거합니다.
$ paste -d , <( cut -d , -f -2 file ) <( cut -d , -f 3 file | cut -d '\' -f -4 ) <( cut -d , -f 5- file )
data,data,c:\path1\folder2\folder3,data,data
data,data,c:\path1\folder2\folder3,data,data
data,data,c:\path1\folder2\folder3,data,data
data,data,c:\path1\folder2\folder3,data,data
처음 두 필드를 세 번째 필드의 경로 이름의 일부로 처리하여 첫 번째 필드를 제거할 수 있지만 cut
이렇게 하면 여전히 파일을 두 번 읽습니다.
$ paste -d , <( cut -d '\' -f -4 file ) <( cut -d , -f 5- file )
data,data,c:\path1\folder2\folder3,data,data
data,data,c:\path1\folder2\folder3,data,data
data,data,c:\path1\folder2\folder3,data,data
data,data,c:\path1\folder2\folder3,data,data
답변3
awk -F "\\" '{gsub(/\.*,/,",",$0);print $1"\\"$2"\\"$3"\\"$4$NF}' file.txt
data,data,c:\path1\folder2\folder3,data,data,data
data,data,c:\path1\folder2\folder3,data,data,data
data,data,c:\path1\folder2\folder3,data,data,data
data,data,c:\path1\folder2\folder3,data,data,data
파이썬
#!/usr/bin/python
import re
qw=re.compile(r'\.*')
k=open('file.txt','r')
for i in k:
respa=re.sub(qw,"",i.strip()).strip().split('\\')
print "{0}\\{1}\\{2}\\{3}{4}".format(respa[0],respa[1],respa[2],respa[3],respa[-1])
산출
data,data,c:\path1\folder2\folder3,data,data,data
data,data,c:\path1\folder2\folder3,data,data,data
data,data,c:\path1\folder2\folder3,data,data,data
data,data,c:\path1\folder2\folder3,data,data,data