1

私は、SED にとって単純であるように見える何かで立ち往生しています。

別のアプリケーションから取得した (一種の) CSV ファイルがあるため、その出力を制御できません。いくつかの前処理は SED で既に行われていますが、最後の処理で行き詰まっています。そのため、3 番目のアプリケーションの使用を避けるために、可能であれば SED で実行したいと考えています。

問題は、ファイルの見出し行 (最初の行) がファイルに沿って繰り返されることですが、残念ながら次のような特徴があります。

  1. 各 CSV ファイルの見出しは、以前は不明でした。各ファイルには独自の見出しがあり、互いに異なる場合があります。
  2. N 行ごとに常に繰り返しが発生するとは限りません (N は既知の固定数です)。
  3. 他のデータ (見出しではない) 行が繰り返される可能性があるため、維持する必要があります。

したがって、次の 2 つのファイルがあるとします。

現金.csv

Name; Amount
John; 3.55
Erick; 4.76
John; 8.99
Name; Amount
Erick; 4.76
Mark; 1.00
Name; Amount
John; 3.55

チェック.csv

Name; Account; Amount
Erick; 345344; 123.00
Mark; 88849; 323.50
Name; Account; Amount
John; 474473; 99.00
Mark; 88849; 323.50
Mark; 88849; 323.50
John; 474473; 99.00

私が望むのは、各ファイルに適用される単一の SED スクリプトで、次のようになります。

Cash.processed.csv

Name; Amount
John; 3.55
Erick; 4.76
John; 8.99
Erick; 4.76
Mark; 1.00
John; 3.55

Check.processed.csv

Name; Account; Amount
Erick; 345344; 123.00
Mark; 88849; 323.50
John; 474473; 99.00
Mark; 88849; 323.50
Mark; 88849; 323.50
John; 474473; 99.00

削除コマンドのパターンとして SED の「ホールド バッファ」を使用できるかどうか疑問に思っていました。

1h     #Hold the first line (headings)
/\h/d  #Use hold buffer as a pattern to delete

「\h」が保留バッファを削除コマンドに返すと仮定します。

返信ありがとうございます。

PS: 次の過度に具体的なコマンドで答えないでください:

1p;/Name; Amount\|Name; Account; Amout/d
4

3 に答える 3

4

sed1つのコマンドから最初の行をキャプチャしてから、それをメインの操作コマンドで使用する必要があると思います。

line1=$(sed 1q $datafile)

sed -e "2,$ {/$line1/d;}" \
    -e '...rest of sed script...' $datafile

最初の行を読み取った後に終了するためsed 1q、データファイルのサイズに関係なくすばやく実行できます。最初の行にスラッシュ(おそらく見出し)または他の正規表現メタ文字が含まれている可能性がある場合は、次の"Name/Number"ようなものを使用することを検討してください。これにより、すべてのスラッシュが次のように置き換えられます.

line1=$(sed '1{s%/%.%g;q;}' $datafile)

私はMacOSX(10.8.1)バージョンのsed、GNUよりも面倒なバージョンでいくつかの面倒をみましたsed。2番目の(メイン)sedコマンドでは、一致が含まれている必要が{...}あり、ドルが分離されている必要があり(または、シェルが無効なパラメーターの置換に腹を立てている)、セミコロンが必要でした。これらの制限のいくつかはおそらくGNUsedでは必要ありませんが、示されているコードはどこでも機能する可能性があります。

于 2012-08-25T14:46:14.403 に答える
2

これはうまくいくかもしれません(GNU sed):

sed '1h;1!{G;/^\(.*\)\n\1/d;s/\n.*//}' file

説明:

  • 1h見出し行をホールドスペース (HS) に格納して印刷します。
  • 1!{G;/^\(.*\)\n\1/d;s/\n.*//}最初の行を除くすべての行に改行を追加し、その後に HS の内容 (つまり、見出し行) を追加します。行の最初の部分を見出し行と比較し、同じ場合はその行を削除します。そうでない場合は、追加された改行と見出し行を削除して、通常どおりに印刷します。

編集:

これは実際、大きなファイルでは非常に遅くなります。より迅速でおそらく理解しやすい解決策は次のとおりです。

sed 's|.*|1!{/^&$/d}|;q' file | sed -f - file

これにより、入力ファイルの最初の行から sed スクリプトが作成されます。

于 2012-08-25T16:08:28.667 に答える
1

awk に興味がある場合:

awk '{if(NR==1){p=$0;print}if(NR>1 && p!=$0)print}' your_file
于 2012-08-25T16:54:59.713 に答える