누군가 아래 변환 쉘 스크립트를 도와줄 수 있습니까?
소스 파일 파일 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
여기서는 하나 이상의 공백, 탭 또는 쉼표를 필드 구분 기호로 간주합니다. 그런 다음 각 줄에 출력을 작성합니다. 마지막으로 결과를 인쇄합니다. 예를 들어 이것은 매우 지저분한 라이너입니다. 예를 들어 인쇄하기 전에 전체 파일을 읽어야 하므로 큰 파일의 경우 메모리를 차지하지만 작은 파일의 경우 트릭을 수행해야 합니다.
귀하의 입력에 따르면 다음과 같은 결과가 발생합니다.
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///
방금 저장한 각 줄에서 공백이 아닌 문자의 두 번째 시퀀스와 모든 후속 공백을 동시에 제거합니다.
결과는 표준 출력으로 인쇄됩니다.
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
방법은 행당 필드 수에 관계없이 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"