誰かが以下の変換シェルスクリプトを助けることができますか?
ソースファイルファイル1:はい
EXCHANGE_ID : 192, 410,
EXCHANGE_DTTM : 2015-06-11+02:18:40+0000, 2015-06-11+02:12:28+0000,
PART_NAME : MRT, LR04,
PART_TRANS_ID : 123, JAS04,
M_NAME : FAILED, FAILED,
M_DTTM : 2015-06-11T02:18:40+0000 2015-06-11T02:12:28+0000
出力は次のとおりです
EXCHANGE _ID : 192
EXCHANGE_ DTTM : 2015-06-11T02:18:40+0000
PART_NAME : MRT
PART_TRANS_ID : 123
M_NAME : FAILED
M _DTTM : 2015-06-11T02:18:40+0000
EXCHANGE _ID : 410
EXCHANGE_DTTM : 2015-06-11T02:12:28+0000
PART_NAME : LR04
PART_TRANS_ID : JAS04
M_NAME : FAILED
M_DTTM : 2015-06-11T02:12:28+0000
これが私が今まで試したことです:
awk '{ for (i = 1; i <= NF; i++) f[i] = f[i] " " $i ; if (NF > n) n = NF } END { for (i = 1; i <= n; i++) sub(/^ */, "", f[i]) ; for (i = 1; i <= n; i++) print f[i] } ' FAILED.csv > TGT_FAILED.out
ただし、これは目的の形式ではなくCSV形式でコンテンツを印刷するだけです。以下は、上記の出力ではなく、実際の出力の例です。
EXCHANGE_ID EXCHANGE_DTTM PART_NAME PART_TRANS_ID M_NAME M_DTTM
: : : : : :
192, 2015-06-11+02:18:40+0000, MRT, 123, FAILED, 2015-06-11T02:18:40+0000
410, 2015-06-11+02:12:28+0000, LR04, JAS04, FAILED, 2015-06-11T02:12:28+0000
答え1
どうですか?
awk -F'[ \t,]+' '{a=a$1"\t"$2"\t"$3"\n"; b=b$1"\t"$2"\t"$4"\n"} END {print a; print b}' data.txt
ここでは、1 つ以上のスペース、タブ、またはコンマをフィールド区切り文字と見なします。次に、各行に出力を作成します。最後に結果を印刷します。たとえば、これは非常に汚れたライナーです。たとえば、印刷する前にファイル全体を読み取る必要があるため、大きなファイルの場合はメモリを消費しますが、小さいファイルの場合はトリックを実行する必要があります。
あなたの入力によると、次のような結果が発生します。
EXCHANGE_ID : 192
EXCHANGE_DTTM : 2015-06-11+02:18:40+0000
PART_NAME : MRT
PART_TRANS_ID : 123
M_NAME : FAILED
M_DTTM : 2015-06-11T02:18:40+0000
EXCHANGE_ID : 410
EXCHANGE_DTTM : 2015-06-11+02:12:28+0000
PART_NAME : LR04
PART_TRANS_ID : JAS04
M_NAME : FAILED
M_DTTM : 2015-06-11T02:12:28+0000
フィールド間隔を適切に指定するには、次のように呼び出しにsprintfを追加できます。
awk -F'[ \t,]+' '{label=sprintf("'%-10s'",$1); a=a""label"\t"$2" "$3"\n"; b=b""label"\t"$2" "$4"\n"} END {print a; print b}' data.txt
これはよりきれいな出力を提供します。
EXCHANGE_ID : 192
EXCHANGE_DTTM : 2015-06-11+02:18:40+0000
PART_NAME : MRT
PART_TRANS_ID : 123
M_NAME : FAILED
M_DTTM : 2015-06-11T02:18:40+0000
EXCHANGE_ID : 410
EXCHANGE_DTTM : 2015-06-11+02:12:28+0000
PART_NAME : LR04
PART_TRANS_ID : JAS04
M_NAME : FAILED
M_DTTM : 2015-06-11T02:12:28+0000
答え2
sed
これをデータに適用する方法を考えたことがない場合は、次のようにします。
sed ' s/\([^, ]\{1,\}\),*/\1,/2
s//\1/3;H;y/,/\n/;P;/^M_D.*/!d
s///;x;s/[^, ]*, *//g
' <<\IN
EXCHANGE_ID: 192, 410,
EXCHANGE_DTTM: 2015-06-11+02:18:40+0000, 2015-06-11+02:12:28+0000,
PART_NAME: MRT, LR04,
PART_TRANS_ID: 123, JAS04,
M_NAME: FAILED, FAILED,
M_DTTM: 2015-06-11T02:18:40+0000 2015-06-11T02:12:28+000
IN
したがって、最初のステップでは、P
カンマが最初に表示される部分までのみ印刷します。すべてのフィールドをカンマで区切ると簡単になります。しかし、そうではないので、作業の半分の程度が正しく機能していることを確認するために消費されます。
とにかく、タイトルとスペース以外の文字の最初のシーケンスのみを印刷します。次に、現在の行のコピーをH
古いスペースに追加してからd
削除します。〜しない限り一致します^M_D
。この場合、x
保存スペースとパターンスペースを変更してから、保存した各行から空白以外の文字s///
の2番目のシーケンスとすべての後続のスペースを同時に削除します。
結果は標準出力として印刷されます。
EXCHANGE_ID: 192
EXCHANGE_DTTM: 2015-06-11+02:18:40+0000
PART_NAME: MRT
PART_TRANS_ID: 123
M_NAME: FAILED
M_DTTM: 2015-06-11T02:18:40+0000
EXCHANGE_ID: 410
EXCHANGE_DTTM: 2015-06-11+02:12:28+0000
PART_NAME: LR04
PART_TRANS_ID: JAS04
M_NAME: FAILED
M_DTTM: 2015-06-11T02:12:28+000
答え3
入力ファイルの処理グループ16行です。2 データ列は単純ですが、制限的で欲張りなリソースアプローチでコーディングオーバーヘッドを最小限に抑えます。ソート6つのデータ行をすべて保存します。
f='src.txt' # input fule
d=' +: +| +|, *' # field delimiter regex
set {2,3} # data columns - not label (which is column 1)
for c; do paste \
<(gawk -F"$d" '1,6{print $1"\t:"}' "$f") \
<(gawk -F"$d" '1,6{print $c}' c=$c "$f") |
column -t; echo; done
次のawk
方法は、1行あたりのフィールド数に関係なく、6行の無限繰り返しグループを処理します。
awk 'BEGIN{ FS=" +: +|, +|,| +"; OFS="\t"; maxw=length("EXCHANGE_DTTM") }
/^EXCHANGE_ID/,/^M_DTTM/{ rn++
if($NF=="") NF--
for(fn=1;fn<=NF;fn++) cell[rn"."fn]=$fn
if(rn==6){
for(fn=2;fn<=NF;fn++)
for(rn=1;rn<=6;rn++)
printf("%-"maxw"s : %s\n"(rn==6?"\n":""), cell[rn"."1], cell[rn"."fn])
rn=0 }}' <"$f"
出力:
EXCHANGE_ID : 192
EXCHANGE_DTTM : 2015-06-11+02:18:40+0000
PART_NAME : MRT
PART_TRANS_ID : 123
M_NAME : FAILED
M_DTTM : 2015-06-11T02:18:40+0000
EXCHANGE_ID : 410
EXCHANGE_DTTM : 2015-06-11+02:12:28+0000
PART_NAME : LR04
PART_TRANS_ID : JAS04
M_NAME : FAILED
M_DTTM : 2015-06-11T02:12:28+0000
bash
以下は上記のスクリプトのバージョンです。awk
論理フローは同じです。エラーチェックと空白行のスキップを追加しました。
set EXCHANGE_DTTM; maxw=${#1}; nl=0 # length of longest label; line number
set -f; declare -A cell; cm=" "; nf=0 # no-globbing; cells-array; cell-margin; number-of-fields
while IFS= read -r line; do ((nl+=1)) # increment line number
[[ $line =~ ^[[:blank:]]*$ ]] && continue # skip blank/empty lines
[[ $line =~ ^EXCHANGE_ID\ * ]] && rn=1 || ((rn+=1)) # reset/increment record number
IFS=" ,"; f=(${line/ : / }); IFS=; f=(${f[@]}) # split line into fields
(( nf )) && (( nf!=${#f[@]} )) && { echo ERROR: field count is not consistent; exit 1; } || nf=${#f[@]}
for (( fn=0; fn<nf; fn++ ));do cell[$rn.$fn]="${f[$fn]}"; done # build cells-array
(( rn==6 )) && {
[[ $line =~ ^M_DTTM\ .* ]] || { echo ERROR: unexpected label found - record $rn$'\n'"$line"; exit 2; }
for (( fn=1; fn<nf; fn++ )) ;do
for (( rn=1; rn<=6; rn++ )) ;do
(( rn==6 )) && b=$"\n" || b=""
printf "%-${maxw}s${cm}:${cm}%s\n$b" "${cell[$rn.0]}" "${cell[$rn.$fn]}"
done; done; } done <"$f"