awk - printf 문제

awk - printf 문제

(편집: 문제가 해결되었습니다. Mac에서 Windows 생성 파일을 사용하고 있었는데 문제는 줄 끝이었습니다. Studio Code에서 파일을 열고 올바른 줄 끝을 설정하면 문제가 해결되었습니다.)

ProduKey처리하고 싶은 파일을 생성했습니다 .awk.

ProduKey는 다음과 같은 출력을 생성합니다.

==================================================
Product Name      : Microsoft Office Professional 2013
Product ID        : 00000-00000-00000-00000
Product Key       : 00000-00000-00000-00000-00000
Installation Folder : C:\Program Files\Microsoft Office\Office15\
Service Pack      : 
Build Number      : 
Computer Name     : PC-000-0
Modified Time     : 06.12.2018 14:03:44
==================================================

==================================================
Product Name      : Windows 10 Pro
Product ID        : 00000-00000-00000-00000
Product Key       : 00000-00000-00000-00000-00000
Installation Folder : C:\Windows
Service Pack      : 
Build Number      : 17763
Computer Name     : PC-000-0
Modified Time     : 18.07.2019 09:50:37
==================================================

나중에 키, 컴퓨터 이름 및 제품 이름을 데이터베이스에 저장하기 위해 csv 파일을 생성하고 싶습니다.

따라서 가능한 CSV는 다음과 같습니다.

PC-000-0;Microsoft Office Professional 2013;00000-00000-00000-00000-00000

지금까지 내 접근 방식은 다음과 같습니다.

    BEGIN {
    RS="\n\n";
    FS="\n";
}
{
    if ($1 ~ /Product Name/) {
        split($1,productArray,":")
        product = productArray[2]
    }

    if ($1 ~ /Product Key/) {
        split($1,keyArray,":")
        key = keyArray[2]
    }

    if ($1 ~ /Computer Name/ ) {
        split($1,computerArray,":")
        computer = computerArray[2]
        #print product 
        #print key
        #print computer
        printf("\n")
        printf("%s ; %s ; %s \n", computer, product, key)
    }
}

내 문제는 문자열을 연결할 수 없다는 것입니다. 아니면 인쇄하려고 할 때 문자열을 덮어쓰게 됩니까? 나는 이것에 대해 몇 시간을 보냈으며 어떤 도움이나 조언이라도 정말 감사하겠습니다.

내 목표를 달성할 수 있는 더 우아한 방법이 있다면 언제든지 알려주시기 바랍니다.

나는 이것을 Mac awk(awk 버전 20070501)에서 사용하고 있지만 Linux 상자도 가지고 있습니다.

미리 감사드립니다.

답변1

여기에서 awk의 레코드 구분 기호( )를 사용할 수 있습니다 RS. 이것을 ==================================================or={50} 로 설정하는 것은 동일하지만 단일 제품과 관련된 각 값 집합을 단일 "행"으로 처리할 수 있는 정규 표현식입니다. 그런 다음 출력 필드 구분 기호( OFS)를 로 설정 ;하고 입력 필드 구분 기호( FS또는 -F옵션) 를 \n(newline) 또는 (newline) 으로 설정하면 :다음과 같은 약간의 트릭을 수행할 수 있습니다(GNU awk 사용).

$ awk RS='={50}' \
      -v OFS=';' \
      -F'[\n:]' \
      'NR%2==0{print $16,$3,$7}' file 
 PC-000-0; Microsoft Office Professional 2013; 00000-00000-00000-00000-00000
 PC-000-0; Windows 10 Pro; 00000-00000-00000-00000-00000

=============================================각 항목에는 위 (50 )와 아래에 하나씩 있으므로 =매초 "행"만 읽으려고 합니다. 그것이 NR%2==0바로 수표의 목적입니다.

각 줄의 시작 부분과 필드 사이에 추가 공백이 있습니다. 문제가 있는 경우 다음을 사용하여 제거할 수 있습니다 sed.

$ awk -v RS='={50}' \
      -v OFS=';' \
      -F '[\n:]' \
      'NR%2==0{print $16,$3,$7}' file | 
        sed -e 's/^ //' -e 's/; /;/g'
PC-000-0;Microsoft Office Professional 2013;00000-00000-00000-00000-00000
PC-000-0;Windows 10 Pro;00000-00000-00000-00000-00000

정규식을 사용하는 것은 RSGNU 확장이므로 macOS에서는 작동하지 않을 수 있습니다. 그렇지 않은 경우 다음을 시도하십시오.

$ awk -v RS='=' \
      -v OFS=';' \
      -F'[\n:]' \
     'NR%50==1 && $2{print $16,$3,$7}' file |
        sed -e 's/^ //' -e 's/; /;/g'

답변2

다음을 시도해 볼 수 있습니다.

awk -F' : ' '/^Product Name/{pn=$2}
             /^Product Key/{pk=$2}
             /^Computer Name/{print $2,pn,pk}' OFS=\; file

필드 구분 기호 는 로 필드 값을 얻을 수 있도록 FS설정됩니다 .:$2

출력 필드 구분 기호 OFS는 으로 설정됩니다 ;.

Computer Name이 문자열은 키워드가 발견될 때마다 인쇄됩니다.

답변3

올바른 방법은 태그 이름과 값 매핑( f[]아래)을 저장하는 배열을 만든 다음 각 레코드 끝에 원하는 값을 인쇄하는 것입니다. 예를 들면 다음과 같습니다.

$ cat tst.awk
BEGIN { OFS=";" }
{
    sub(/\r$/,"")
    tag = val = $0
    sub(/[[:space:]]*:.*/,"",tag)
    sub(/[^:]+[[:space:]]*:[[:space:]]*/,"",val)
    f[tag] = val
}
/^=/ && (cnt++)%2 {
    print f["Computer Name"], f["Product Name"], f["Product Key"]
    delete f
}

$ awk -f tst.awk file
PC-000-0;Microsoft Office Professional 2013;00000-00000-00000-00000-00000
PC-000-0;Windows 10 Pro;00000-00000-00000-00000-00000

원하는 경우 동일한 방법을 사용하여 전체 입력 파일을 CSV로 쉽게 변환할 수도 있습니다.

$ cat tst.awk
BEGIN { OFS=";" }
!/^=/ {
    sub(/\r$/,"")
    tag = val = $0
    sub(/[[:space:]]*:.*/,"",tag)
    sub(/[^:]+[[:space:]]*:[[:space:]]*/,"",val)
    if ( !seen[tag]++ ) {
        tags[++numTags] = tag
    }
    f[tag] = val
}
/^=/ && (cnt++)%2 {
    if ( !doneHdr++ ) {
        for (tagNr=1; tagNr<=numTags; tagNr++) {
            tag = tags[tagNr]
            printf "\"%s\"%s", tag, (tagNr<numTags ? OFS : ORS)
        }
    }

    for (tagNr=1; tagNr<=numTags; tagNr++) {
        tag = tags[tagNr]
        printf "\"%s\"%s", f[tag], (tagNr<numTags ? OFS : ORS)
    }

    delete f
}

$ awk -f tst.awk file
"Product Name";"Product ID";"Product Key";"Installation Folder";"Service Pack";"Build Number";"Computer Name";"Modified Time"
"Microsoft Office Professional 2013";"00000-00000-00000-00000";"00000-00000-00000-00000-00000";"C:\Program Files\Microsoft Office\Office15\";"";"";"PC-000-0";"06.12.2018 14:03:44"
"Windows 10 Pro";"00000-00000-00000-00000";"00000-00000-00000-00000-00000";"C:\Windows";"";"17763";"PC-000-0";"18.07.2019 09:50:37";""

OFS=";"로 변경 OFS=","하면 Windows에서 두 번 클릭하여 Excel에서 올바르게 표시할 수 있는 파일이 출력됩니다.

관련 정보