동일한 파일에서 블록별로 값 가져오기

동일한 파일에서 블록별로 값 가져오기

다음 내용이 포함된 "SAMPLE.txt"라는 파일이 있습니다.

P1
10,9:6/123456
P2
blah blah
P1
10,9:5/98765
P2
blah
blah
P1
blah blah
P2

출력 파일 "RESULT.txt"를 원합니다.

Value1:123456
Value2:98765
Value3:NULL

먼저 P1과 P2 부분 사이의 콘텐츠를 가져온 다음 10,9*/ 값을 찾아 다른 값으로 저장해야 합니다. 특정 P1-P2 블록에 이 값이 없으면 "NULL"로 저장하고 싶습니다.

위의 코드를 shell/awk에 어떻게 작성하나요?

저는 스크립팅을 처음 접했습니다.

답변1

이것은 작동하며 완전히 이식 가능합니다.

sed '\|^P1.*|!d;s||Value:|
     :n
     N;\|\nP2|!bn
     s|:.*\n10,9[^/]*/|:|
     s|\n.*||;s|:$|:NULL|' 

프로세스는 다음과 같습니다.

  1. 먼저 ^다룹니다.P1

  2. 현재 행이 !일치하지 않으면 d삭제됩니다.

  3. 그렇다면 다음 P1으로 교체하십시오.Value:

  4. :n그런 다음 ext 태그를 설정 하고 Next 라인을 가져옵니다.

  5. 찾을 \nP2수 없으면 ext 태그 로 돌아가서 찾을 때까지 다시 시도하세요.!b:n

  6. :.*\n10,9그런 다음 첫 번째 발생 /까지 모든 문자 발생을 제거합니다 .

  7. \n사용 가능한 첫 번째 ewline과 모든 후속 문자를 제거합니다 .

  8. :마지막 문자가 뒤에 오는 콜론 이면 Value문자열이 삽입됩니다 NULL.

6단계와 7단계가 작동합니다. 6단계에서는 \n원하는 숫자 문자열 앞에 있는 ewline을 제거하지만, 없으면 다음 \newline은 바로 다음의 문자열이 됩니다 Value:.모든 것7단계로 이동합니다.

이것이 실제로 작동하는 것입니다:

sed '\|^P1.*|!d;s||Value:|
     :n
     N;\|\nP2|!bn
     s|:.*\n10,9[^/]*/|:|
     s|\n.*||;s|:$|:NULL|' <<\DATA
P1
10,9:6/123456
P2
blah blah
P1
10,9:5/98765
P2
blah
blah
P1
blah blah
P2
DATA

산출:

Value:123456
Value:98765
Value:NULL

답변2

사용 perl(전체 파일을 메모리에 저장하더라도):

 perl -0777 -ne 'while (/P1\n(.*?)\nP2/gs) {
   printf "Value%d:%s\n", ++$n, $1 =~ /^10,9.*\// ? $'\'': "NULL"}'

답변3

일방 perl통행:

$ perl -F'/' -alne '
    if (/P1/../P2/ and $_ !~ /^P/) {
        print "Value@{[++$i]}:",$F[1]?$F[1]:"NULL";
    }
' file
Value1:123456
Value2:98765
Value3:Null

해결책 awk:

$ awk -F'/' '/P2/{f=0};/P1/{f=1;next};f{print "Value"++i":"($2?$2:"Null")}' file
Value1:123456
Value2:98765
Value3:Null

답변4

다들 감사 해요. 마침내 내 문제를 해결한 코드 조각은 다음과 같습니다.

nawk -v fname="${filename}" -F '/|:' '

    function isnum(x){return(x==x+0)}

    /P1/,/P3/{
            # Found start increment i reset variables go to next line
            if(/P1/){
                   ++i 
                   fid ="" 
                   count++
                   next
                }

            # Found end validate variable and print go to next line
            if(/P3/){
                printf "%s|",count
                printf "%s|",isnum(fid)?fid:"NULL"
                  next 
                }
            if(!fid && /36,59:*/)
                {
                    fid = $NF
                }
        ' ${filename} >>output.txt

하지만 이제 또 다른 문제가 생겼고 이에 대해 별도의 스레드를 만들었습니다.

여러분이 도움을 줄 수 있다면 여기 링크를 참조하세요.

https://stackoverflow.com/questions/24277167/finding-and-replacing-text-inside-awk-block?noredirect=1#comment37509363_24277167

관련 정보