abc.txt ファイルです。
NAME="MARK" StartTime="14:11:26.710583" TotalElapsedTime="0" Pool="10" ThreadsReached="0"
NAME="MARK" StartTime="14:11:26.710583" TotalElapsedTime="0" Pool="10" ThreadsReached="0"
次の形式のabc.csv出力が必要です。
NAME StartTime TotalElapsedTime Pool ThreadsReached
MARK 14:11:26.710583 0 10 0
MARK 14:11:26.710583 0 10 0
答え1
デフォルトのCSV形式はカンマを,
フィールド区切り文字と見なすため、次のGNUはsed方法:
sed -e '1iNAME,StartTime,TotalElapsedTime,Pool,ThreadsReached' -e 's/[^=]*="\([^"]*\)"/\1,/g; s/,$//g' file
出力:
NAME,StartTime,TotalElapsedTime,Pool,ThreadsReached
MARK,14:11:26.710583,0,10,0
MARK,14:11:26.710583,0,10,0
1i
- インサートヘッダーファイルの最初の行の前の行
s/[^=]*="\([^"]*\)"/\1,/g
- すべての属性値を抽出
答え2
while IFS= read -r l; do
set -f; IFS==; set -- $l; shift; N=$#
for arg
do
set -- ${1+"$@"} "$(expr " $arg" : ' "\(.*\)"')"
done
shift "$N"; IFS=,; echo "$*"
done < abc.txt
while IFS= read -r l; do
set -f; IFS==; set -- $l; shift
while case ${#} in 1 ) break ;; esac; do
expr " $1" : ' "\(.*\)"'
shift
done | tr \\n ,; expr " $*" : '.*"\(.*\)"'
done < abc.txt
perl -lne '$,=",";
print /(?:^|\h)\K[^=]*/g if $. == 1;
print /="([^"]*)"/g;
' abc.txt
説明する
/(?:^|\h)\K[^=]*/g
Perlコードは、最初の行から始まり、ディスプレイの水平方向のスペースの左側または行の先頭にある文字を取得するために読み取る正規表現を介してフィールド名を抽出します。次に、カンマに設定して印刷します。non=
\h
^
OFS
$,
- すべての行(最初の行を含む)に対して正規表現でフィールド値を抽出します。
/="([^"]*)"/g
これは二重引用符で囲まれた文字列を抽出することで読み取られます(二重引用符がエスケープされないと仮定)。文字列は左側に隣接しています。その上に等号があります。次に、この値のセットstdout
をOFS
。 - ループソリューションの場合は、
while
まずトークン化せずに行をそのまま読みます。次にIFSをanに設定し、=
最初のフィールドを拒否します。これで、すべてのフィールドの形式は次のようになります。"..."...
次に、ユーティリティを使用してexpr
二重引用符内の値を豊富にして$@
配列に配置します。ループが終わったら、for
元の要素()を削除し$N
て残ったのは私たちが望むものです。最後に、IFSをコンマに設定し、拡張してコンマで接続します$*
。