あるファイルの内容を別のファイルに置き換えようとしています。
入力ファイルTest.txt
:
HLRSN = 3
IMSI = 404212109727229
KIVALUE = A24AD11812232B47688ADBF15CE05CA9
K4SNO = 1
CARDTYPE = SIM
ALG = COMP128_3
HLRSN = 3
IMSI = 404212109727230
KIVALUE = A24AD11812232B47688ADBF15CE05CB8
K4SNO = 1
CARDTYPE = SIM
ALG = COMP128_3
HLRSN = 3
IMSI = 404212109727231
KIVALUE = A24AD11812232B47688ADBF15CE05CD6
K4SNO = 1
CARDTYPE = SIM
ALG = COMP128_3
他のテキストファイルから希望の出力:
3,404212109727229,A24AD11812232B47688ADBF15CE05CA9,1,SIM,COMP128_3
3,404212109727230,A24AD11812232B47688ADBF15CE05CB8,1,SIM,COMP128_3
3,404212109727231,A24AD11812232B47688ADBF15CE05CD6,1,SIM,COMP128_3
答え1
簡単に:
awk -v RS= -v OFS=, '{print $3,$6,$9,$12,$15,$18}'
空記録区切り記号(RS=
)できるようにする短絡モードここで、レコードは一連の空行に分かれています。レコード内にはデフォルトのフィールド区切り文字が適用されるため(レコードはスペースで区切られています)、各レコードの目的のフィールドは3番目、6番目、9番目です。
私たちは変わる出力フィールド区切り文字はカンマ文字(OFS=,
)で、目的のフィールドを印刷します。
答え2
一方bash
通行:
declare -a out
EOF=false
IFS=$'='
until $EOF; do
read -r skip val || EOF=true
if [ ! -z "$val" ]
then
out+=("${val//[[:space:]]/}")
else
tmp="${out[@]}"
printf '%s\n' "${tmp// /,}"
out=()
fi
done < file
どのように動作しますか?
out
出力行を保持する配列を宣言し、EOF
ファイルの終わりを追跡するように変数を設定し、IFS
入力フィールド区切り文字を使用しますread
。- ファイルの終わりを読むまでファイルの各行を読み、最後のフィールドの値を変数に設定します
val
。 if [ ! -z "$val" ]
:変数の長さがゼロで$val
ないことを確認するために、スペースを削除して$val
配列にプッシュしますout
。- 長さが
$val
0の場合、つまり空の行またはファイルの終わりが表示されたら、配列内のすべての要素をout
変数tmpに割り当て、すべての空白変数を設計した出力履歴区切り文字tmp
に置き換えます。,
out
さらなる作業のためにnullに設定してください。
もう一つのクリーンで短い解決策は、次のものを使用することですperl
。
$ perl -F'=' -anle '
BEGIN { $, = "," }
push @out,$F[-1] if @F;
print @{[map {s/\s// && $_} @out]} and @out = ()
if /^$/ or eof;
' file
3,404212109727229,A24AD11812232B47688ADBF15CE05CA9,1,SIM,COMP128_3
3,404212109727230,A24AD11812232B47688ADBF15CE05CB8,1,SIM,COMP128_3
3,404212109727231,A24AD11812232B47688ADBF15CE05CD6,1,SIM,COMP128_3
答え3
以下をファイルに保存します(例split.awk
:)。
BEGIN {
RS="\n\n";
FS="\n";
ORS=",";
}
{
for (i=1;i<=NF;i++)
{
split($i, sf, "= ")
print sf[2]
}
printf "\n"
}
次に、次を実行します。
awk -f split.awk Test.txt
または、コマンド全体を1行で実行します。
awk 'BEGIN {RS="\n\n";FS="\n";ORS=",";}{for(i=1;i<=NF;i++){split($i, sf, "= ")print sf[2]}printf "\n"}' Test.txt
仕組みは次のとおりです。
ブロックは
BEGIN
最初に一度実行され、レコード区切り記号(RS
)を2つの改行に設定し、フィールド区切り記号(FS
)を単一の改行に設定します。出力レコード区切り文字(ORS
)はコンマに設定されています。次に、レコードの各フィールド(
NF
現在のレコードのフィールド数)を繰り返し、「=」に分割します。ORS
次に、各分割の間にコンマ()を使用してその分割の右側を印刷します。各行の後に改行文字が印刷され、CSV形式を提供します。
答え4
使用ミラー(mlr
)私たちは、単一の改行で区切られたフィールドを含み、等号で区切られたキーと値のペアを含む二重改行で区切られたレコードでデータを読み取ることができます。余分な空白と空の列(これらの区切り文字を使用してデータを読み取った結果、各フィールド値の先頭にスペースを追加)を削除してからCSVに変換できます。
$ mlr --ips = --ifs lf --irs lflf --ocsv clean-whitespace then remove-empty-columns Test.txt
HLRSN,IMSI,KIVALUE,K4SNO,CARDTYPE,ALG
3,404212109727229,A24AD11812232B47688ADBF15CE05CA9,1,SIM,COMP128_3
3,404212109727230,A24AD11812232B47688ADBF15CE05CB8,1,SIM,COMP128_3
3,404212109727231,A24AD11812232B47688ADBF15CE05CD6,1,SIM,COMP128_3
出力にCSVヘッダーを含めない場合は、このオプションをmlr
一緒に使用してください-N
。 Millerは、埋め込み区切り文字または引用符を含むすべてのフィールドを自動的に引用します。