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/g
645 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
_
' '
이렇게 하면 원하는 출력을 얻을 수 있습니다.