sed를 사용하여 테이블의 행 조인

sed를 사용하여 테이블의 행 조인

쿼리에 다음 테이블이 있지만 +구분 기호는 아래 예와 같이 "설명" 아래에 새 행을 만드는 것입니다.


TYPE+DESCRIPTION+PRIORITY+DATE
1+text1+HIGH+Aug 15
+text2  
2+text+LOW+Aug 11
3+text+LOW+Aug 11
4+text1+HIGH+Aug 15
+text2  
+text3

sed를 사용하여 다음과 같이 보이게 하려면 어떻게 해야 하나요?

TYPE    DESCRIPTION      PRIORITY DATE
1       text1 text2      HIGH     Aug 15
2       text             LOW      Aug 11
3       text             LOW      Aug 11
4       text text2 text3 HIGH     Aug 15

나는 시도했다:

sed -n '1{h;n};/^ *+ */{s// /;H;n};{x;s/\n//g;p};${x;p}' 

하지만 오류가 발생했습니다(sed: 명령이 깨졌습니다). 감사합니다.

답변1

awk '
    BEGIN{OFS=FS="+"}
    {sub(/[[:blank:]]+$/,"")}  #Removes trailing blanks
    NF==4{print line;line=$0}
    NF==2{x=$2;$0=line;$2=$2" "x;line=$0}
    END{print line}
' file | column -ts "+"

그 뒤에 있는 주요 아이디어는 if 가 NF==2두 번째 필드를 $2이전 행의 두 번째 필드에 넣는 것입니다. 그래서 무슨 일이 일어나는가?

1+text1+HIGH+Aug 15 #Puts this in "line" variable
+text2              #Transfer 2nd field to "line" second field
# Resulting in...
1+text1 text2+High+Aug 15

column+이 미세한 최종 출력을 생성하기 위해 출력에서 ​​제거되었습니다.

TYPE  DESCRIPTION        PRIORITY  DATE
1     text1 text2        HIGH      Aug 15
2     text               LOW       Aug 11
3     text               LOW       Aug 11
4     text1 text2 text3  HIGH      Aug 15

답변2

"도메인 불가지론" 만들기awk

tac file | awk 'BEGIN{FS="+"}
    {flds=(NF>flds)?NF:flds;for (i=1; i<=NF; i++) {f=(length($i)>0)?gensub(/ +$/,"","g",$i)" ":"";fld[i]=f fld[i]}}
    $1>0{for (i=1; i<=flds; i++) printf fld[i]"+"; printf "\n"; delete fld}' | 
    tac | column -ts "+"

TYPE   DESCRIPTION         PRIORITY   DATE     
1      text1 text2         HIGH       Aug 15   
2      text                LOW        Aug 11   
3      text                LOW        Aug 11   
4      text1 text2 text3   HIGH       Aug 15  

송곳

$1이 비어 있지 않고 설정되었을 때 인쇄할 시간임을 알 수 있도록 파일을 뒤집습니다.FS

tac file | awk 'BEGIN{FS="+"}

최대 수를 계산하고 flds, 필드를 반복하고, 잘라내고 공백을 확인하고, 필드별로 배열에 로드하여 집계합니다.

    {flds=(NF>flds)?NF:flds;for (i=1; i<=NF; i++) {f=(length($i)>0)?gensub(/ +$/,"","g",$i)" ":"";fld[i]=f fld[i]}}

비어 있지 않으면 $1라인을 출력하고 배열을 재설정합니다.

    $1>0{for (i=1; i<=flds; i++) printf fld[i]"+"; printf "\n"; delete fld}' | 

파이프를 통해 tac뒤집어서 column아름답게 만드는 데 사용하세요.

    tac | column -ts "+"

편집하다

두 번째 루프가 정말 마음에 들지 않으며, 파이프에 있는 망치로 칠 gensub수 있을 때 각 필드에서 중지하고 테스트를 단순화합니다. sed우아한 느낌은 아니네요.

그래서 여기에골프를 치다버전은 그냥느끼다나에게 더 나은:

tac file | awk 'BEGIN{FS="+"}
    {flds=(NF>flds)?NF:flds;
        for (i=1; i<=NF; i++) {fld[i]=$i" "fld[i];
        if ($1) printf fld[i]"+"}}
    $1{ printf "\n"; delete fld}' |
    sed -E "s/  +/ /g" | tac | column -ts "+" 

답변3

돌아가서 sed 버전 간의 가능한 차이점을 읽고 처음부터 다시 작성하세요. 이것이 효과가 있기를 바랍니다:

:r
    $!N
    y:+:,:
    /\n,/{
        s:^\([^,]\{1,\},[^,]\{1,\}\)\([^\n]\{1,\}\)\n,\([^ \n]\{1,\}\).*$:\1 \3\2:
        br
    }
    $!P
    $!D

산출:

TYPE,DESCRIPTION,PRIORITY,DATE
1,text1 text2,HIGH,Aug 15
2,text,LOW,Aug 11
3,text,LOW,Aug 11
4,text1 text2 text3,HIGH,Aug 15

답변4

perl -0pe 'while(s/(.*?)\+(.*?)\+(.*)\n\+(.*)/$1+$2 $4+$3/g){}' file
  • perl -0 - 모든 입력을 삼키다
  • s/(.*?)\+(.*?)\+(.*)\n\+(.*)/$1+$2 $4+$3/gA+B+...C\n+D가능하다면 전환을 하십시오 A+B D+...C.

관련 정보