2013-04-18 3 views
1

다음 형식의 레코드가있는 텍스트 파일이 있다고 가정하십시오. 여기서 FS은 일반적으로 쉼표이며, RS은 일반적으로 줄 바꿈입니다.awk에서 줄 바꿈이 포함 된 필드를 처리 할 수 ​​있습니까?

그러나이 규칙의 예외는 필드가 따옴표 안에 있으면 줄 바꿈과 쉼표를 필드의 일부로 처리해야한다는 것입니다.

"This field contains 
line breaks and is 
quoted but it 
should be treated as a 
single field",1,2,3,"another field" 

어떻게 나는 아직도 $1,$2...에 액세스 할 수있는 나는 보통하는 것처럼하지만, 필드 위의 해석과, 제대로 이러한 파일을 구문 분석 AWK 사용할 수 있습니까?

나는 이미 this wiki page을 보았지만 거기에 제시된 해결책은 줄 바꿈 문제를 해결하지 못합니다.

+2

가능할 수도 있지만 매우 깨지기 쉽습니다. Awk는 대부분의 유닉스 도구와 마찬가지로 한 번에 한 줄씩 데이터를 처리하도록 설계되었습니다. 귀하의 도구 세트와의 "계약"이 깨어지면 모든 고통이 이어질 것입니다. $ 1 등을 참조 할 필요가 있기 때문에 나는 어떤 종류의 해킹도 제안 할 가치가 없다. 나는 틀렸다는 것을 증명할 수있을 것이다 ;-) "\ n"의 대체물로 & # *^@와 같은 것을 사용하여 레코드를 평평하게하는 전후 필터가 마음에 떠오르는 유일한 것이다. 행운을 빕니다. – shellter

+0

이것은 사소한 것처럼 보이지 않을 수 있습니다 ... awk이 유일한 옵션입니까? –

+0

아니요, 파이썬으로 작성할 수는 있지만,이 문제는 awk에서 실제로는 구분 기호 문제 일 것입니다. 근본적인 한계가 있기 때문에 awk에서 작동하도록하려고했습니다. – merlin2011

답변

0

가능한 해결책은 완벽하지는 않지만 awk 'BEGIN{RS="\""}{...}'입니다. 이렇게하면 레코드 구분 기호가 "으로 재설정되지만 필드 구분 기호는 공백으로 남습니다. 문제는 첫 번째와 마지막으로 "이 일부 레코드의 구분으로 일치하기 때문에 파일에 두 개의 빈 레코드를 추가한다는 것입니다.

예 : condtion NR>1를 추가하여 데이터

END OF RECORD - 
This field contains 
line breaks and is 
quoted but it 
should be treated as a 
single field END OF RECORD This - field 
,1,2,3, END OF RECORD ,1,2,3, - 
another field END OF RECORD another - field 

END OF RECORD - 

당신은 첫 번째를 건너 뛸 수 있습니다에 적용 할 때

awk 'BEGIN{RS="\""} {print $0,"END OF RECORD",$1,"-",$2}' 

이 결과를 생성합니다. 마지막 하나는 파일에 몇 개의 레코드가 있는지 모르기 때문에 조금 까다 롭습니다. 배열에 인쇄 할 값을 저장하고 문에 for주기를 사용하여 인쇄하고 파일의 첫 번째 및 마지막 레코드를 건너 뛸 수 있습니다.

0

awk에서 파일을 올바르게 구문 분석하려면 csvquote라는 프로그램을 사용하면 따옴표로 묶인 필드에 나타나는 쉼표와 개행 문자를 awk와 혼동하지 않는 인쇄 할 수없는 문자로 임시로 바꿀 수 있습니다. 이 프로그램은 awk가 필드 구분자를 항상 나타내는 쉼표와 항상 레코드 분리자를 나타내는 개행에 의존 할 수있는 형식으로 데이터를 santize합니다.

를 사용하려면이 같은 컷/AWK/...를 포함하는 파이프 라인을 포장 :

csvquote /tmp/foo.csv | tail +2 | awk -F, '{print $3 $2}' | csvquote -u 

당신은 여기에 코드를 찾을 수 있습니다 https://github.com/dbro/csvquote

하나주의해야 할 점은 당신이 원하는 경우이다 필드 안의 쉼표와 개행 문자를 검색하려면 인쇄되지 않는 문자를 대신 검색해야하므로 작업이 더 복잡해집니다. 이 작업을보다 쉽게 ​​수행 할 방법을 찾고 있다면 csvfix 도구를 살펴 봐야합니다.

또 다른 옵션은 awk의 FPAT를 사용하는 것이지만 필드에 이스케이프 된 인용 부호가 포함되어 있으면 작동하지 않습니다. http://www.gnu.org/software/gawk/manual/html_node/Splitting-By-Content.html

0

아마도 레코드 분리 자로 두 줄의 새 줄을 사용할 수 있습니다.당신의 주어진 파일에 대한

awk -v RS="\n\n" -v FS="," '...' file 

의 파일 자체와 함께 파일 번호를 표시하자 :

당신은 또한 필드 구분자로 쉼표를 설정하면, 다음이 당신이 필드로 텍스트의 각 블록을 처리 할 수 ​​있습니다
$ awk -v RS="\n\n" -v FS="," '{for (i=1; i<=NF; i++) print i, $i}' file 
1 "This field contains 
line breaks and is 
quoted but it 
should be treated as a 
single field" 
2 1 
3 2 
4 3 
5 "another field" 
+0

이중 줄 바꿈 분리가 필요하고 원래 질문에 한 줄 바꿈 기호 구분 기호가 필요하기 때문에 여러 레코드에서 작동하지 않는 것처럼 보입니다. – merlin2011

+0

레코드가 이중 줄 바꿈으로 분리되어 있으면 참으로 작동합니다. 나는 더 나은 해결책을 찾아 내려고 노력할 것이다, 내가 관리 할 수 ​​있는지 보자. :) – fedorqui