コマンドラインによるCSVファイルの処理:2番目の列の値が同じ場合は、連続する行エントリ間の中間行のみを削除します。

コマンドラインによるCSVファイルの処理:2番目の列の値が同じ場合は、連続する行エントリ間の中間行のみを削除します。

列が2つしかないCSVファイルがあります(ただし、場所行)と常にアスタリスク(*)文字で始まり、3つ以上の列にまたがる可能性のある不規則な行があります。 Linuxコマンドラインのみを使用すると、予想される動作は次のとおりです。

  1. 3つ以上の連続したデータ行が2番目の列の値が等しい場合は、中央の行を削除します。開始線と終了線を維持します。
  2. アスタリスクで始まる不規則な線の維持

たとえば、次のようなCSVがある場合:

    0,Apple
    1,Apple
    2,Apple
    * Checkpoint
    * Another checkpoint
    3,Apple
    4,Apple
    5,Box
    6,Box
    7,Citrus
    8,Box
    9,Apple
    10,Apple
    11,Apple
    12,Dove
    13,Citrus
    * Sudden checkpoint, * Leftover checkpoint note 1, * Leftover checkpoint note N
    14,Citrus
    15,Citrus
    16,Citrus
    17,Apple
    18,Citrus

それでは、次のようになります。

    0,Apple
    * Checkpoint
    * Another checkpoint
    4,Apple
    5,Box
    6,Box
    7,Citrus
    8,Box
    9,Apple
    11,Apple
    12,Dove
    13,Citrus
    * Sudden checkpoint, * Leftover checkpoint note 1, * Leftover checkpoint note N
    16,Citrus
    17,Apple
    18,Citrus

上記の例では、1~3行、10行、14~15行が削除されました。

どんな答えでもよろしくお願いします。

乾杯

ベストアンサー1

使用awk:

BEGIN { FS = "," }

/^[*]/ { print; next }

{
        if (NR > 1 && $2 == word) {
                tail = $0
                ++count
        } else {
                if (count) print tail
                word = $2; count = 0
                print
        }
}

END { if (count) print tail }

スクリプトawkは、無条件で始まるすべての行を印刷します*。行がそのような行ではなく、2番目のフィールドの単語が私たちが覚えている単語である場合、そのレコードを変数tail(同じ単語を含む一連のレコードの最後のレコードと同じ「尾」)に保存します。フィールド)。

2番目のフィールドが次の場合いいえ以前と同じで、tailレコードを印刷します。以前の実行の複数のレコードがある場合は、新しい単語を覚えていて、同じ単語の2番目のフィールドに現在のレコード(新しい実行の1つ以上のレコードの最初のレコード)を印刷します。 )。

提供されたデータをテストし、次のように仮定します。シンプルなCSV(埋め込み区切り文字や改行文字などがないことを意味します):

$ awk -f script file
0,Apple
* Checkpoint
* Another checkpoint
4,Apple
5,Box
6,Box
7,Citrus
8,Box
9,Apple
11,Apple
12,Dove
13,Citrus
* Sudden checkpoint, * Leftover checkpoint note 1, * Leftover checkpoint note N
16,Citrus
17,Apple
18,Citrus

上記と似ていますが、使用ミラー( mlr)これはCSVをサポートし、複雑な引用符付き文字列を含むCSVレコードを処理できます。

if (is_not_null(@word) && $2 == @word) {
        @tail = $*;
        false # omit this record for now
} else {
        is_not_null(@tail) {
                emit @tail # emit the tail record
        }
        @word = $2; @tail = null;
        true  # emit this record
}

end { is_not_null(@tail) { emit @tail } }

filterawkこれは、上記のコードとよく似たロジックを使用して入力データセットのレコードを含めるか省略するMillerサブコマンドの式です。 Millerがこの文字で始まる行に移動するように、コマンドラインでuseを*使用できます。入力をヘッダーレスCSVとして扱うには、withを--pass-comments-with='*'使用します。--csv-N

$ mlr --pass-comments-with='*' --csv -N filter -f script file
0,Apple
* Checkpoint
* Another checkpoint
4,Apple
5,Box
6,Box
7,Citrus
8,Box
9,Apple
11,Apple
12,Dove
13,Citrus
* Sudden checkpoint," * Leftover checkpoint note 1"," * Leftover checkpoint note N"
16,Citrus
17,Apple
18,Citrus

おすすめ記事