「完全な」データセットを持つ数行しかないセミコロンで区切られたデータファイルがあります。彼ら最後にデータセットが適用される行ブロックの位置。シェルスクリプト(または同様のコマンドラインツール)を使用して、完全に入力されたこの行のデータを上記の行に追加したいと思います。
たとえば、私のファイルに次のデータが含まれているとします。
86540701
86951202
86262402
86509002
86770802
86459902
86301002
86485102
86556002;Vivo Y11;1630000;NULL;;;
86447404
86161405
86388604
86106105
86426405;Xiaomi Redmi 8A Pro (Redmi 8A Dual);1465000;4;;;
次のように完全な行を見つけ、そのデータを上記の不完全な行に置き換えることができるようにします。
86540701;Vivo Y11;1630000;NULL;;;
86951202;Vivo Y11;1630000;NULL;;;
86262402;Vivo Y11;1630000;NULL;;;
86509002;Vivo Y11;1630000;NULL;;;
86770802;Vivo Y11;1630000;NULL;;;
86459902;Vivo Y11;1630000;NULL;;;
86301002;Vivo Y11;1630000;NULL;;;
86485102;Vivo Y11;1630000;NULL;;;
86556002;Vivo Y11;1630000;NULL;;;
86447404;Xiaomi Redmi 8A Pro (Redmi 8A Dual);1465000;4;;;
86161405;Xiaomi Redmi 8A Pro (Redmi 8A Dual);1465000;4;;;
86388604;Xiaomi Redmi 8A Pro (Redmi 8A Dual);1465000;4;;;
86106105;Xiaomi Redmi 8A Pro (Redmi 8A Dual);1465000;4;;;
86426405;Xiaomi Redmi 8A Pro (Redmi 8A Dual);1465000;4;;;
答え1
これは私たちが使用できる仕事です。tac
ファイルを逆順に解析します。
tac file | awk -F';' 'NF > 1 {p = substr($0,index($0,FS))} {print $1 p}' | tac
そのため、行を保存せずに読み取った後に各行を印刷します。
後で使用するために、行の先頭から最後までNF > 1
部分文字列を保存するとき。FS
答え2
awk
2チャンネルアプローチに基づく別のソリューション(GNUawk
またはnawk
このgensub()
機能が必要):
awk -F';' 'FNR==NR{if (NF>1) data[++i]=gensub(/^[^;]+/,"","1");next}
{if (NF==1) $0=$0 data[j+1]; else j++;} 1' input.csv input.csv
これによりファイルが2回スキャンされます。最初は、複数のフィールドを含む行の「データ部分」配列を作成します。 2番目に、欠落しているデータセクションを置き換え、「完全な」行が見つかるたびに配列カウンタをインクリメントして、次のデータセクションに次の行を置き換えます。
答え3
使用sed
:
sed -E '
/;/!{ :a N;/;/!{ s/\n/-/;ta; }; };
/;/ { s/\n/-/; };
:c s/([^-]*)-([^;]*)(;.*)$/\1\3\n\2\3/; tc' infile
答え4
GNU sed
拡張正規表現モードをオンにした状態で使用-E
- レコードを保留状態に保存し、ジョブの開始時にセミコロンレコードを待ちます。
- セミコロンラインに会うと、パターンスペースの最後の部分(=セミコロンライン)がパターンスペースの最初の部分に追加され、最初の部分が印刷され削除されるマージプロセスが開始されます。これはパターン空間が不足するまで続く。
$ sed -Ee '/\n/ba
H;/;/!d;z;x;D;:a
s/\n(.*\n)?[^;]+(;.*)/\2&/
P;/\n.*\n/D;s/.*\n//
' file
$ perl -lne '$, = ";";
push(@A,$_),next if !/;/;
my $a = s/.*?;//r;
print $_, $a for splice @A;
print;
' file