0이 있거나 없는 CSV 계산을 위한 Bash 스크립트

0이 있거나 없는 CSV 계산을 위한 Bash 스크립트

여기에 제가 사용하고 있는 스크립트가 있습니다. 나는 이제 이것을 확장하고 싶습니다.

POSIXLY_CORRECT=1 awk -F ';' -v OFS=';' '
  {print $0, NR == 1 ? "Price" : $1 ? $1 : $3 * 1.2}' < file.csv

열 1에 0이 없으면 필드 3을 1.2로 계산하지만 필드 1에 0이 있거나 아무것도 없으면 필드 3을 1.2로 계산하는 것이 가능합니까?

내 스프레드시트 또는 CSV 파일은 다음과 같습니다.

Sales Price;External ID;Cost;Internal reference;Name;Sales Description
73;1000-04;141,35;1000-04;Jabra GN 1000 RHL Remote Handset Lifter;Manueller Lifter bzw. Hook-Switch
0;0440-729;61,72;0440-729;Jabra GN 1000 RHL, zbh. für Siemens Optiset; Siemens Optiset Telefone
215;2126-82-04;221,8;2126-82-04;Jabra 2100 Mono QD 3-in-1 Set;Typ: 82 E-STD, Noise-Cancelling Mikrofonarm: Flexibel
0;01.01.8800;11,3;01.01.8800;Jabra Kabel QD -> RJ10 Standard spiral;RJ10

결과는 다음과 같아야합니다

Sales Price;External ID;Cost;Internal reference;Name;Sales Description;Price
73;1000-04;141,35;1000-04;Jabra GN 1000 RHL Remote Handset Lifter;Manueller Lifter bzw. Hook-Switch;73
0;0440-729;61,72;0440-729;Jabra GN 1000 RHL, zbh. für Siemens Optiset; Siemens Optiset Telefone;74,064
215;2126-82-04;221,8;2126-82-04;Jabra 2100 Mono QD 3-in-1 Set;Typ: 82 E-STD, Noise-Cancelling Mikrofonarm: Flexibel;215
0;01.01.8800;11,3;01.01.8800;Jabra Kabel QD -> RJ10 Standard spiral;RJ10;13,56

이제 다음 내용으로 calc.sh를 만들었습니다.

#!/bin/sh
POSIXLY_CORRECT=1 awk '
    BEGIN { FS=OFS=";" }
    {
        if (NR == 1) val = "Price"
        else         val = ($9 ? $5 * 1.2 : $9)
        print $0, val
    }
' /test.csv

다음과 같이 파일을 실행합니다.

calc.sh > /opt/price/result.csv

결과는 다음과 같습니다.

Sales Price;External ID;Cost;Internal reference;Name;Sales Description
;Price
73;1000-04;141,35;1000-04;Jabra GN 1000 RHL Remote Handset Lifter;Manueller Lifter bzw. Hook-Switch
;
0;0440-729;61,72;0440-729;Jabra GN 1000 RHL, zbh. für Siemens Optiset; Siemens Optiset Telefone
;
215;2126-82-04;221,8;2126-82-04;Jabra 2100 Mono QD 3-in-1 Set;Typ: 82 E-STD, Noise-Cancelling Mikrofonarm: Flexibel
;
0;01.01.8800;11,3;01.01.8800;Jabra Kabel QD -> RJ10 Standard spiral;RJ10;
  1. 가격은 두 번째 줄에 있습니다. 왜?

  2. xx열에 가격이 출력되도록 어딘가를 지정할 수도 있나요?

답변1

기존 논리를 변경하려면 다음 안내를 따르세요.

열 1에 0이 없으면 1.2를 사용하여 열 3을 계산합니다.

당신은 무엇을 원하십니까:

필드 1이 0이거나 None이면 필드 3은 1.2로 계산됩니다.

가지고 있는 것을 바꾸십시오:

$1 ? $1 : $3 * 1.2

부정적인 조건:

!$1 ? $1 : $3 * 1.2

또는 값의 순서를 바꿉니다.

$1 ? $3 * 1.2 : $1

값의 순서를 바꾸는 것이 $1 ?조건부 부분의 음수와 "else", 부분의 이중 음수를 방지하므로 더 좋을 것입니다 : $1.

바라보다https://en.wikipedia.org/wiki/Ternary_conditional_operator삼항 표현식을 읽고 사용하는 방법을 알아보세요.

그렇긴 하지만, 삼항 표현식을 중첩하지 마십시오. 이렇게 하면 코드를 읽기가 어려워지고 항상 삼항 표현식 주위에 괄호를 넣어 읽기 쉽게 만들고 특정 컨텍스트에서 특정 awk 사용을 방지합니다. 구문 오류가 발생했습니다(예를 들어 다음을 참조하세요.https://unix.stackexchange.com/a/588743/133219).

그래서 대신:

{print $0, NR == 1 ? "Price" : $1 ? $3 * 1.2 : $1}

다음과 같이 작성해야 합니다.

{
    if (NR == 1) val = "Price"
    else         val = ($1 ? $3 * 1.2 : $1)
    print $0, val
}

또는 유사합니다.

또한 다음 대신에:

awk -F ';' -v OFS=';' 'script'

다음을 사용하는 것을 고려해보세요:

awk 'BEGIN{FS=OFS=";"} script'

따라서 FS와 OFS가 동일한 값을 가져야 하는 경우 동일한 구분 기호( )를 2곳에 하드코딩할 필요가 없습니다. ;이렇게 하면 코드가 약간 더 깔끔해지고 1곳만 변경하면 됩니다(결정한 경우 / 경우). 이를 수행하려면) 구분 기호를 변경하십시오.

위 내용을 이해하는 데 어려움을 겪고 계신 것으로 알고 있으므로 명확성을 위해 전체 스크립트는 다음과 같아야 한다고 제안합니다.

POSIXLY_CORRECT=1 awk '
    BEGIN { FS=OFS=";" }
    {
        if (NR == 1) val = "Price"
        else         val = ($1 ? $3 * 1.2 : $1)
        print $0, val
    }
' file.csv

바라보다https://www.gnu.org/software/gawk/manual/gawk.html#Locale-influences-conversions.NET 대신 로케일에 POSIXLY_CORRECT=1소수 구분 기호가 필요한 이유는 무엇입니까 ?,.

관련 정보