csplit 및 붙여넣기

csplit 및 붙여넣기

텍스트 파일이 있습니다열.txt아래와 같이 두 개의 열이 있습니다.

  1 1.1
  2 4.0
  3 3.2
  start newset
  1 2.2
  2 6.1
  3 10.3
  4 2.1
  start newset
  1 18.2
  2 4.3

다음과 같은 경우 새 열 쌍을 생성하려면 이를 여러 열로 변환해야 합니다.뉴스 수집 시작도착했다. 그래서 내가 원하는 출력 텍스트 파일은 다음과 같습니다. (문자열이 있는 줄을 삭제하고 싶습니다.뉴스 수집 시작):

  1 1.1 1 2.2 1 18.2
  2 4.0 2 6.1 2 4.3
  3 3.2 3 10.3
        4 2.1

답변1

이것을 시도해 볼 수 있습니다.

awk '
    /^start newset/ {
        max = max>i ? max : i
        i = 0
        set++
        next
    }
    {
        ++i
        a[i][set] = $0
    }
    END {
        for( i=1 ; i<=max ; i++ ) { 
            for( j=1 ; j<=set ; j++ )
                b = b OFS a[i][j]
            sub( "\t" , "" , b )
            print b
            b=""
        }
    }
' set=1 OFS='\t' column.txt

답변2

csplit 및 붙여넣기

csplit패턴에 따라 파일을 여러 파일로 분할하는 데 사용됩니다 . 그런 다음 paste.

awk 'NF' column.txt | csplit --suppress-matched -s -z -f INTERIM -n 4 - '/start newset/' '{*}' ; paste INTERIM* | expand -t 6,13 ; rm -f INTERIM*

명확성을 위해 동일한 코드를 다시 형식화했습니다.

awk 'NF' column.txt | \
csplit --suppress-matched -s -z -f INTERIM -n 4 - '/start newset/' '{*}' ;

paste INTERIM* | \
expand -t 6,13 ;

rm -f INTERIM*

설명하다:

  • awk 'NF' column.txt
    빈 줄을 제거하세요. 그렇지 않으면 입력 파일의 빈 줄이 출력에 추가 열 구분 기호를 배치합니다.
  • 분할
    • --suppress-matched
      출력에 분할 패턴이 포함된 행을 포함하지 마십시오.
    • -s
      출력 파일에 대한 요약 정보를 표시하지 않습니다.
    • -z
      빈 출력 파일을 생성하지 마십시오(즉, 입력 파일의 인접한 두 줄에 분할 패턴이 포함된 경우).
    • -f INTERIM
      분할 파일의 파일 이름은 이 문자열로 시작됩니다.
    • -n 4
      분할된 파일의 파일 이름은 이 숫자를 포함하는 숫자로 끝납니다.
    • -
      STDIN먼저 입력 파일을 실행하므로 에서 입력을 가져옵니다 awk.
    • '/start newset/'
      이 정규식을 포함하는 첫 번째 줄에서 입력 파일을 분할합니다.
    • '{*}'
      해당 정규식이 포함된 각 추가 줄에서 입력 파일을 계속 분할합니다.
  • paste INTERIM*
    임시 파일을 추가합니다.
  • expand -t 6,13
    연결된 파일 사이의 열 간격을 조정합니다(예: 두 번째 파일은 열 6에서 시작하고 세 번째 파일은 열 13에서 시작).
  • rm -f INTERIM*
    임시 파일을 삭제합니다.

입력 파일 예 column.txt:

1 1.1
2 4.0
3 3.2
start newset
1 2.2
2 6.1
3 10.3
4 2.1
start newset
1 18.2
2 4.3

출력 예:

1 1.1 1 2.2  1 18.2
2 4.0 2 6.1  2 4.3
3 3.2 3 10.3 
      4 2.1  

입력 파일의 줄과 최종 출력의 줄을 들여쓰면 좀 더 복잡해집니다.

입력 파일 예 column.txt:

  1 1.1
  2 4.0
  3 3.2
  start newset
  1 2.2
  2 6.1
  3 10.3
  4 2.1
  start newset
  1 18.2
  2 4.3
  • 추가 처리 전에 들여쓰기를 제거하려면 awk 'NF'로 변경하세요 .awk 'NF { sub(/^ +/,"",$0) ; print $0 }'
  • 들여쓰기된 출력 expand -t 6,13으로 변경합니다 .awk '{ print " " $0 }' | expand -t 8,15

출력 예:

  1 1.1 1 2.2  1 18.2
  2 4.0 2 6.1  2 4.3
  3 3.2 3 10.3 
        4 2.1  

답변3

일부 임시 파일을 통한 라우팅:

$ awk 'BEGIN { n = 1 } /^start newset/ { n++; next } { name = sprintf("tmp-%04d", n); print >name }' file

이렇게 하면 터미널에 출력이 생성되지 않지만 1보다 크거나 같은 0으로 채워진 4자리 정수라는 tmp-n이름 의 파일이 생성됩니다. n각 데이터 세트마다 하나의 파일이 있습니다.

그런 다음 이러한 임시 파일을 함께 붙여넣을 수 있습니다.

$ paste tmp-*
1 1.1   1 2.2   1 18.2
2 4.0   2 6.1   2 4.3
3 3.2   3 10.3
        4 2.1

또는 탭 대신 공백을 구분 기호로 사용하세요.

$ paste -d ' ' tmp-*
1 1.1 1 2.2 1 18.2
2 4.0 2 6.1 2 4.3
3 3.2 3 10.3
 4 2.1

만약 있다면데이터의 세트 수에 따라 두 가지 문제가 발생합니다.

  1. 두 번째 코드 블록을 awk변경하면 이를 방지할 수 있습니다 .awk

    { name = sprintf("tmp-%04d", n); print >name }
    

    도착하다

    { name = sprintf("tmp-%06d", n); print >>name; close(name) }
    

    (또한 더 큰 숫자를 허용하도록 형식 문자열 변경에 유의하세요.)

  2. paste패턴이 tmp-*너무 많은 파일로 확장되므로 명령을 실행하는 데 문제가 있을 수 있습니다. 이것이 문제인지 알려주시면 수정하겠습니다(파일의 열을 추가하여 결과를 작성하는 쉘 루프가 발생합니다 tmp-*).

답변4

$ awk '$1+0>=1{a[$1]=a[$1]" "$0}END{for (i in a)print a[i]}' file.txt 
 1 1.1 1 2.2 1 18.2
 2 4.0 2 6.1 2 4.3
 3 3.2 3 10.3
 4 2.1

위의 awk 명령은 a라는 배열을 생성하고 첫 번째 열을 기준으로 값을 저장/추가합니다. 파일을 완전히 읽은 후에는 배열 값을 인쇄하면 됩니다.

step 1 : a[1] = "1 1.1"
step 2 : a[2] = "2 4.0"
step 3 : a[3] = "3 3.2"
step 4 : ignore the line # 4. because the first column is not numeric
step 5 : a[1] = "1 1.1 1 2.2"
step 6 : a[2] = "2 4.0 2 6.1".
....
...
once the file is fully procssed by awk, then just print the array values a[1],a[2],a[3]...a[n]

관련 정보