ドライバーlist
次の例に示すように、ファイルリストを印刷するサブコマンドがあります。
gdrive list
出力:
Id Name Type Size Created
1sV3_a1ySV0-jbLxhA8NIEts1KU_aWa-5 info.pdf bin 10.0 B 2018-08-27 20:26:20
1h-j3B5OLryp6HkeyTsd9PJaAtKK_GYyl 2018-12-ss-scalettapass dir 2018-08-27 20:26:19
同様のツールを使用してこの出力を解析しようとしましたが、成功しませんでしawk
たsed
。
問題は、サイズ列の空の「フィールド」と列の動的幅にあります。
この出力を解析する方法を知っている人はいますか?
答え1
awkは固定幅データを処理できます。まず、列の幅を決定する必要があります。
fieldwidths=$(head -n 1 file | grep -Po '\S+\s*' | awk '{printf "%d ", length($0)}')
値は"36 26 7 9 7 "
- 最後のフィールドが7文字より大きいです。任意に70文字に設定しました。
fieldwidths=${fieldwidths/% /0}
それでは、データを読み込んでCSVに変換してみましょう。
awk -v FIELDWIDTHS="$fieldwidths" '{
for (i=1; i<=NF; i++) {
val = $i
sub(/ *$/, "", val)
gsub(/"/, "\"\"", val)
printf "%s\"%s\"", (i==1 ? "" : ","), val
}
print ""
}' file
出力:
"Id","Name","Type","Size","Created"
"1sV3_a1ySV0-jbLxhA8NIEts1KU_aWa-5","info.pdf","bin","10.0 B","2018-08-27 20:26:20"
"1h-j3B5OLryp6HkeyTsd9PJaAtKK_GYyl","2018-12-ss-scalettapass","dir","","2018-08-27 20:26:19"
Perlと同じ機能を持っています。
perl -lne '
if ($. == 1) {
@head = ( /(\S+\s*)/g );
pop @head;
$patt = "^";
$patt .= "(.{" . length($_) . "})" for @head;
$patt .= "(.*)\$";
}
print join ",", map {s/"/""/g; s/\s+$//; qq("$_")} (/$patt/o);
' file
答え2
Perl
このunpack
関数を使用してヘッダー(最初の行)を確認して解凍テンプレートを動的に生成します。
perl -lpe '
$fmt //= join "", map("A" . length(), /\H+\h+(?=\H)/g), "A*";
$_ = join ",", map { s/"/""/gr =~ s/(.*)/"$1"/r } unpack $fmt;
' input-file.txt
説明する:
-p
perl
このファイルは行単位で使用されます。各行(レコードとも呼ばれる)をといいます$_
。別の効果は、-p
次のレコードをインポートする前に現在のレコードを自動的に印刷することです。-l
2つのことをグループ化ORS = RS = \n
- 正規表現は、
/\H+\h+(?=\H)/g
最後のフィールドを除くすべてのフィールドを取得し、そのフィールドをに供給する必要がありますmap
。 map
これらのフィールドの長さを計算し、各フィールドにプレフィックス「A」を追加します。- 上記の最後のフィールドを選択する代わりに、包括的な「A *」を追加しました。
join
次に、ヌル区切り文字を使用する文字列に渡して1つの文字列にまとめます。したがって、解凍された形式はすでに使用可能であり、//=
演算子が関数であるdefined-or
ため再評価されません。- 動的に生成された解凍形式を使用して、ヘッダーを含むすべての行に適用を進めます。
unpack
提供された形式を使用して文字列(この場合は現在の行)を解凍し、解凍されたフィールドをエクスポートします。- 次に、放出されたフィールドを
map
ここに入力して各フィールドを1つずつ処理し、{ ... }
コードに記載されている手順を実行します。私たちの場合、各フィールドで次のことを行います。 a)二重引用符。 b)フィールドを二重引用符で囲みます。 - フィールドを編集したら、
map
そのフィールドを入力し、join
コンマを使用してリンクして,
素敵な小さなファイルを作成しますCSV
。 - 添付:
unpack
(ASCIIの場合A)フォーマット文字を使用するunpack
ときに生成されたフィールドの末尾のスペースを切り捨てる必要はありません。A
出力:
"Id","Name","Type","Size","Created"
"1sV3_a1ySV0-jbLxhA8NIEts1KU_aWa-5","info.pdf","bin","10.0 B","2018-08-27 20:26:20"
"1h-j3B5OLryp6HkeyTsd9PJaAtKK_GYyl","2018-12-ss-scalettapass","dir","","2018-08-27 20:26:19"
これはツールを使用して実行できますが、sed
2段階のアプローチが必要です。まず、入力のヘッダー行を使用してsed
動的にスクリプトを生成し、次に入力ファイル(ヘッダーを含む)を操作して必要な操作を実行します。 、図に示すように:
if="input-file.txt"
cmd=$(< "$if" head -n 1 | perl -lne 'print join $/, reverse map { $s += length();qq[s/./\\n/$s] } /\H+\h+(?=\H)/g')
sed -e '
'"${cmd}"'
s/"/""/g
s/[[:blank:]]*\n/","/g
s/.*/"&"/
' < "$if"