반대 효과를 갖는 awk 시스템 호출

반대 효과를 갖는 awk 시스템 호출

DATA특정 키워드( , ) 사이에 여러 개의 데이터 덩어리가 포함된 데이터 파일이 있습니다 END. 나는 이것을 사용하여 awk해당 청크에서 얻은 파일 이름을 기반으로 데이터 청크를 별도의 파일로 추출합니다. 일부 데이터 덩어리는 동일한 이름을 공유하므로 blockname파일(" ")이 이미 존재하는 경우 증분 정수를 사용하여 각 출력 파일의 이름을 바꿉니다.

#cat input.file
useless stuff1
DATA blockname1
data1
data1
END
useless stuff2
DATA blockname2
data2
data2
END
useless stuff3
DATA blockname1
data3
data3
END
useless stuff4

3개의 출력 파일 이 예상됩니다 blockname1. (마지막 파일에 정수가 어떻게 할당되는지 확인하세요.)blockname2blockname1_1

#cat blockname1
DATA blockname1
data1
data1
END

(다른 사람들도 그에 따라...)

이제 다음 스크립트는 내가 원하는 방식으로 작동합니다.

awk '/DATA/,/END/ {
     if ( $1 ~ /DATA/ )
       { block=$2 ; i=0 ; file=block
         while ( system("test ! -e " file ) )
           { i++ ; file=block"_"i ; print file }
       }
       print $0 > file
     }' input.file

내 문제는 while루프와 해당 시스템 호출에 있습니다.

system("test -e " file)존재하면 TRUE이고 file아직 존재하지 않으면 FALSE가 되기를 원합니다 . 즉, 루프가 존재하는 경우에만 루프가 실행되기 시작하고 (새) 루프가 아직 존재하지 않으면 중단됩니다.filewhilefilefile

그러나 사용하면 system("test -e " file)(그리고 사용하면 장황해집니다 print file.) 동일한 이름의 무한 루프가 증가하고 정수 접미사가 증가하며 대신 system("test !-e " file)원하는 결과가 제공됩니다.

그래서 제가 예상했던 것과 정반대였습니다.

답변1

내 생각엔 문제는 종료 상태 test와 루프 조건 while사이의 TRUE와 FALSE의 서로 다른 정의 에 있습니다 awk.

양수 test명령의 종료 코드는 0TRUE이고, 음수 명령의 종료 코드는 1FALSE입니다.

그러나 awk루프 내에서는 FALSE 및 TRUE로 while해석되므로 정의는 정반대입니다.01

예를 들어:

awk '{ while ( 0 ) ; { print "0" } }' file

아무런 출력도 생성하지 않지만

awk '{ while (1) ; { print "1" } }' file

무한한 s를 인쇄합니다 1.

따라서 가장 좋은 방법은 다음 조합을 지정하는 것입니다.

while ( system("command") == 0 )

또는

while ( system("command") == 1 )

각기.

그래서 내가 아는 한

while ( system("test -e " file ) == 0 ) 

예상되는 동작을 보여줍니다.

답변2

awk system()실행한 명령의 종료 상태를 반환합니다. 성공하면 0, 실패하면 != 0입니다. 간단한 예를 들어 다음을 실행해 볼 수 있습니다.

v = system("date");

v는 0이 될 것이다

실행하는 경우:

v = system("dat");

v는 127이거나 0이 아닌 값일 수 있으며 dat 명령이 없거나 찾을 수 없는 경우 운영 체제는 오류를 반환합니다.

답변3

무슨 뜻인지 이해한다면, 목표는 input.file의 내용을 다양한 파일로 추출하여 동일한 이름을 가진 블록을 잃지 않는 것입니다.

이런 경우이고 추출하기 전에 대상 디렉터리가 항상 비어 있는 경우 더 나은(더 빠른) 솔루션이 있습니다.

awk '
/DATA/{
    block=$2;
    n = blocks[block]++;
    file=block (n? "_" n: "");  
}
/DATA/,/END/{
    print > file
}' input.file

이렇게 하면 awk는 파일이 존재하는지 테스트하기 위해 새 쉘을 N 번 실행할 필요가 없습니다.

노트:

  • awk의 필드 구분 기호가 이미 공백이므로 BEGIN 블록이 필요하지 않습니다.
  • '\'작은따옴표는 이미 여러 줄이므로 줄 끝은 필요하지 않습니다.

관련 정보