탭과 공백이 포함된 텍스트에서 균일한 열을 만드는 방법은 무엇입니까?

탭과 공백이 포함된 텍스트에서 균일한 열을 만드는 방법은 무엇입니까?

file.txt가장 간단한 형태로 다음 과 같은 자동 생성 파일이 있다고 가정해 보겠습니다 file.txt.

 Source                    Destination                Maximum To  Maximum From Average Total   Average To           Average From
(192.168.1.1)   (192.168.1.2)       202.89 Kbps    0 bps         645 bps 645 bps 0 bps

column나는 이 명령을 여러 가지 변형으로 시도했지만 아무 소용이 없었습니다. 이 출력을 다음과 같이 만들려면 어떻게 해야 합니까?

Source         Destination     Maximum To     Maximum From     Average Total     Average To     Average From
(192.168.1.1)  (192.168.1.2)   202.89 Kbps    0 bps            645 bps           645 bps        0 bps

이 작업을 수행하는 방법을 알아야 할 것 같지만 공백을 그리는 중이며 지금까지 예상대로 작동하는 항목을 찾지 못했습니다.

편집하다:아래의 설명과 답변은 sed원래 예제와 완벽하게 맞습니다. (저는 실제로 설명에 있는 솔루션이 더 간단하고 파이핑을 포함하지 않기 때문에 선호합니다 tr.) 즉, 두 솔루션 모두 여러 줄 파일에서 정확히 동일한 성능을 발휘합니다. 여기에는 실제로 file.txt다양한 길이의 수백 줄의 IPv4 주소가 포함됩니다. sed지금까지 두 솔루션 모두 원본에 비해 더 정확한 결과를 다음과 같이 반환합니다 file.txt.

원본 파일.txt:

Source                    Destination                Maximum To  Maximum From Average Total   Average To           Average From
(10.10.10.21)     (192.168.123.122)      18.90 Kbps     0 bps         131 bps 131 bps 0 bps
(10.10.10.22)     (192.168.123.122)       10.88 Kbps     0 bps         23 bps 23 bps 0 bps
(10.10.10.23)     (192.168.123.123)       10.88 Kbps     0 bps         23 bps 23 bps 0 bps
(192.168.123.123) (192.52.168.123)       0 bps          22.84 Kbps    1.17 Kbps 0 bps     1.17 Kbps
(192.168.123.124)  (192.52.168.123)       0 bps          10.87 Kbps    19 bps 0 bps  19 bps

업데이트된 file.txt(지금까지 제안된 솔루션을 사용한 후):

Source                              Destination        Maximum To  Maximum From  Average Total  Average To  Average From
(10.10.10.21)                       (192.168.123.122)  18.90 Kbps  0 bps         131 bps        131 bps     0 bps
(10.10.10.22)                       (192.168.123.122)  10.88 Kbps  0 bps         23 bps         23 bps      0 bps
(10.10.10.23)                       (192.168.123.123)  10.88 Kbps  0 bps         23 bps         23 bps      0 bps
(192.168.123.123) (192.52.168.123)  0 bps              22.84 Kbps  1.17 Kbps     0 bps          1.17 Kbps
(192.168.123.124)                   (192.52.168.123)   0 bps       10.87 Kbps    19 bps         0 bps       19 bps

이 오프셋 경고를 해결하기 위한 업데이트된 솔루션이 있습니까?

답변1

스크립트는 OP의 샘플 데이터를 기반으로 합니다.

sed '
    s/\s\s\+/:/g
    s/\([a-z)]\)\s\([(0-9A]\)/\1:\2/g
    ' file.txt | 
column -s: -t
  • 찾기 쉬운 구분 기호를 변경하여 시작하세요(2 \s단계 이상).:
  • 두 번째 단계에서는 나머지 가능한 구분 기호를 찾습니다.
    • 소문자와 숫자 사이
    • 뒤쪽에)
    • 앞으로A
  • 열 구분 기호를 사용하여 문자열 형식 지정:

답변2

다음 Perl 스크립트는 처음 두 필드에 각각 하나의 "단어"만 있고 나머지 필드에는 각각 두 개의 "단어"가 있다는 지식을 바탕으로 입력을 탭으로 구분된 필드로 변환합니다. 그런 다음 출력은 다음으로 파이프됩니다.column -s $'\t' -t

이것은 다소 서투르고 무차별적인 접근 방식이지만 작동합니다.

#! /usr/bin/perl 

use strict;

while(<>) {
    my (@F, @fields, $i);

    @F=split;
    $fields[0] = $F[0] ;
    $fields[1] = $F[1] ;
    for $i (0..4) {
      $fields[$i + 2] = $F[$i*2 + 2] . ' ' . $F[$i*2 + 3];
    }

    print join("\t",@fields),"\n";
}

사용 방법은 다음과 같습니다.

$ ./bandwidth.pl bandwidth.txt | column -s $'\t' -t 
Source             Destination        Maximum To  Maximum From  Average Total  Average To  Average From
(10.10.10.21)      (192.168.123.122)  18.90 Kbps  0 bps         131 bps        131 bps     0 bps
(10.10.10.22)      (192.168.123.122)  10.88 Kbps  0 bps         23 bps         23 bps      0 bps
(10.10.10.23)      (192.168.123.123)  10.88 Kbps  0 bps         23 bps         23 bps      0 bps
(192.168.123.123)  (192.52.168.123)   0 bps       22.84 Kbps    1.17 Kbps      0 bps       1.17 Kbps
(192.168.123.124)  (192.52.168.123)   0 bps       10.87 Kbps    19 bps         0 bps       19 bps

그런데 이는 구분된 필드에 구분 기호(예: 공백)를 사용하는 것이 결코 좋은 생각이 아닌 이유를 보여주는 좋은 예입니다. 이는 필요한 것보다 상황을 더 어렵게 만들 뿐이며 파일 내용과 구조에 대한 사전 지식 없이는 구분 기호와 필드 내용을 구별할 수 있는 안정적인 방법이 없습니다.

답변3

고쳐 쓰다:다음 예에서 명명된 전체 원본의 사본을 사용하십시오 full_original.txt.

$ sed 's/\((\)/ \1/g;s/\(Average\)/ \1/g;s/ \([0-9]\)/  \1/g;s/\(\S\) \(\S\)/\1_\2/g' full_original.txt | column -t | tr _ ' '
Source             Destination        Maximum To  Maximum From  Average Total  Average To  Average From
(10.10.10.21)      (192.168.123.122)  18.90 Kbps  0 bps         131 bps        131 bps     0 bps
(10.10.10.22)      (192.168.123.122)  10.88 Kbps  0 bps         23 bps         23 bps      0 bps
(10.10.10.23)      (192.168.123.123)  10.88 Kbps  0 bps         23 bps         23 bps      0 bps
(192.168.123.123)  (192.52.168.123)   0 bps       22.84 Kbps    1.17 Kbps      0 bps       1.17 Kbps
(192.168.123.124)  (192.52.168.123)   0 bps       10.87 Kbps    19 bps         0 bps       19 bps

설명하다

이 솔루션의 대부분은 여러 개별 문제가 있고 이를 개별적으로 해결하는 "분할 및 정복" 접근 방식을 따릅니다. 마지막으로 마무리 터치를 위한 마법 명령을 통해 column조립됩니다 tr.

  • Greedy/Global의 경우 기본 패턴이므로 s/searchstring/replacestring/g'g번째 일치 항목뿐만 아니라 모든 일치 항목에 적용됩니다.
  • 우리는 그룹화를 사용하므로 검색 섹션에서 "첫 번째 그룹인 경우", "두 번째 그룹인 경우" 등으로 \(somegroup\)다시 인쇄 할 수 있습니다.\1\2
  • 세미콜론을 사용하면 파이프보다 더 효율적으로 ;여러 검색 및 바꾸기 명령을 하나의 인스턴스에 넣을 수 sed있으므로 여러 sed를 실행할 수 있습니다 sed command | sed command | sed command .....
  • s/\((\)/ \1/g...123) (19...OP가 발견한 오프셋 문제를 피하기 위해 괄호로 묶인 두 개의 IP 값을 서로 두 칸 이상 밀어내는 작업을 처리합니다 . 왼쪽 대괄호를 일치시키고 (앞에 공백을 붙여서 이를 수행합니다 space.(
  • s/\(Average\)/ \1/g특별히 분리된 부품이 없어 Maximum From Average Total나중에 찾아서 교체하기 어렵게 만드는 문제를 해결하기 위해 처음에는 각 항목 앞에 추가 공간을 추가했습니다.Average
  • s/ \([0-9]\)/ \1/g645 bps 645 bps 0 bps발생 앞에 공백을 추가하여 space+number원본 텍스트의 필드 값을 분리 하면 space+space+number다시 후속 sed 명령이 이를 구별하는 데 도움이 됩니다.
  • 마지막 sed 명령 s/\(\S\) \(\S\)/\1_\2/g은 해결 방법으로, non-space+space+non-space공백이 밑줄이 되도록 그룹화하여 검색하고 변경합니다. 이것은 Maximum To나중에 column사용하는 명령을 위해 함께 보관됩니다 .Maximum_To
  • | column -t이것을 열 명령에 파이프하면 기본적으로 다음과 같이 man column표시됩니다. By default, the column command will merge multiple adjacent delimiters into a single delimiter when using the -t option따라서 텍스트 사이의 가변 공백을 단일 구분 기호로 처리합니다.
  • 열은 텍스트 정렬을 위해 서식 다시 지정도 수행합니다.
  • | tr _ ' '마지막으로 공백을 밑줄( )로 변환 명령을 사용하여 해결 방법을 실행 취소 하고 모든 을 다시 공백으로 변환합니다._tr_' '

이렇게 하면 원하는 출력을 얻을 수 있습니다.

관련 정보