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行目です。なぜ?

  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小数点区切りが必要なのはなぜですか?,.

おすすめ記事