이 AWK 스크립트가 어떻게 작동하는지 알아내려고 노력 중입니다.

이 AWK 스크립트가 어떻게 작동하는지 알아내려고 노력 중입니다.

내 가게에는 누군가가 이전에 작성한 AWK 코드 조각이 있지만 문서화되어 있지 않아 이를 해석하는 방법을 모릅니다.

awk -F'~"' ' {gsub(/~/, " ", $3); print $1"~\""$2"~\""$3"~\""$4}' INFILE.dat > OUTFILE.dat

상상하다:

구분된 텍스트 파일 에는 ~아래와 같은 12개의 열이 있습니다.

본질적으로 문자인 데이터는 열 3, 9, 10과 같이 큰따옴표로 묶여 있습니다.

1235678~2005-04-13-13.49.42.149512~"10"~9999.44~2004-07-22~2006-05-22~2006-07-22~2006-05-29~"2000~2001"~"N"~0.00~9999.63~2005-04-13-13.49.42.149556
                                                                                            ^^^^^^^^^^^

9열에는 필드 구분 기호가 varchar(100) 포함될 수 있습니다 ~.

위의 awk 코드는 ~열 9를 공백으로 부분적으로 변환합니다 gsub().

이 코드가 어떻게 작동하는지 정확히 말해 줄 수 있는 사람이 있나요?

입력 파일은 INFILE.dat. 출력 파일은 OUTFILE.dat.

예상되는 출력과 관련하여 변경해야 할 유일한 것은 9번째 열의 데이터입니다. 사이에는  공백을 사용해야 ~합니다 . "2000~2001"출력 라인은 다음과 같습니다:

1235678~2005-04-13-13.49.42.149512~"10"~9999.44~2004-07-22~2006-05-22~2006-07-22~2006-05-29~"2000 2001"~"N"~0.00~9999.63~2005-04-13-13.49.42.149556
                                                                                            ^^^^^^^^^^^

답변1

기존 코드가 불필요하게 복잡합니다. 특정 데이터의 특정 필드에만 적용되도록 취약하고 하드 코딩되어 있으므로 이해하기 어렵고 실제로 폐기해야 합니다.

awk를 사용하여 큰따옴표 안의 문자 또는 문자열을 다른 문자 또는 문자열로 바꾸는 관용적 방법은 다음과 같습니다.

$ awk 'BEGIN{FS=OFS="\""} {for (i=2; i<=NF; i+=2) gsub(/~/," ",$i)} 1' file
1235678~2005-04-13-13.49.42.149512~"10"~9999.44~2004-07-22~2006-05-22~2006-07-22~2006-05-29~"2000 2001"~"N"~0.00~9999.63~2005-04-13-13.49.42.149556

이는 행을 "구분된 필드로 분할하므로 모든 짝수 필드는 따옴표 사이의 필드입니다( "a"~"b"=1) null2)a3) ~4)b5) null) 따라서 해당 짝수 필드는 우리가 작업하는 필드입니다.

그것이(또는 원래 스크립트) 무엇을 하는지 확실하지 않다면, 맨 페이지를 탐색한 후 사용된 다양한 변수의 값이 무엇인지 확인하기 위해 몇 가지 인쇄 문을 추가하기만 하면 됩니다.

데이터는 본질적으로 CSV의 하위 집합이지만 ~대신 ,구분 기호로 사용하는 방법은 다음을 참조하세요.awk를 사용하여 csv를 효율적으로 구문 분석하는 가장 강력한 방법은 무엇입니까awk를 사용하여 CSV를 처리하는 방법을 알아보세요.

awk를 사용하려면 awk에 대해 알아야 할 몇 가지 사항이 있습니다. 원본 스크립트와 이 새 스크립트는 awk 언어의 매우 기본적인 구성 요소를 사용합니다. Arnold Robbins의 "Effective AWK 프로그래밍, 5판" 책을 구하여 최소한 기본 사항을 배우고 다른 것이 필요한 경우 준비할 수 있도록 하십시오. 컨텐츠 편집시 편리하게 사용하세요.

답변2

인류파일이 ~구분되어 있다고 생각할 수도 있지만 awk 표현식에서는 파일이 일련의 두 문자로 구분되어 있다고 생각합니다 ~". 따라서 귀하가 제공한 예제 라인에는 다음이 포함됩니다.4개필드:

  1. 1235678~2005-04-13-13.49.42.149512
    
  2. 10"~9999.44~2004-07-22~2006-05-22~2006-07-22~2006-05-29
    
  3. 2000~2001"
    
  4. N"~0.00~9999.63~2005-04-13-13.49.42.149556
    

따라서 응용 프로그램은 gsub(/~/, " ", $3)그 중 (단일)을 공백으로 바꿉니다. 이 문자열은 원본을 대체합니다. 외부 따옴표는 문자열 구문이고 내부 따옴표를 보호하려면 백슬래시가 필요합니다. 개인적으로 나는 just 또는 인쇄 목적을 사용하는 것을 피하고 싶습니다.~2000~2001""~\""FSprint $1 FS $2 FS $3 FS $4모두사용된 필드

awk -F'~"' 'BEGIN{OFS=FS} {gsub(/~/, " ", $3)} 1'

그러나 이 접근 방식은 취약해 보입니다. 9번째 "실제" 필드가 3번째로 구분된 필드 내에 존재하는지 확인할 수 있습니까 ~"? 인용된 필드에 구분 기호가 존재할 수 있음을 인식하는 솔루션을 탐색하는 것이 좋습니다. 예를 들어 CSV에 구분 기호가 존재할 수 있습니다. 그러한 도구 중 하나는밀러, 할 수 있는 곳 1

$ mlr -N --csv --fs '~' put '$9 = gsub($9,"~"," ")' INFILE.dat 
1235678~2005-04-13-13.49.42.149512~10~9999.44~2004-07-22~2006-05-22~2006-07-22~2006-05-29~2000 2001~N~0.00~9999.63~2005-04-13-13.49.42.149556

  1. Miller의 새 버전에는서브시스템(문자열 대체) 이 경우에 바람직한 함수

관련 정보