열 형식 데이터 구문 분석

열 형식 데이터 구문 분석

일부 열 형식 데이터가 있는데 이를 더 형식화하고 싶습니다. 다음과 같습니다.

$ getStats | grep ESTABLISHED | column -t
all  tcp  117.54.56.131:80       <-  10.42.100.211:63752   ESTABLISHED:ESTABLISHED
all  tcp  10.42.120.201:63752    ->  219.224.67.112:31180  ->                       137.51.59.141:80       ESTABLISHED:ESTABLISHED
all  tcp  77.221.237.24:443      <-  10.42.100.117:59999   ESTABLISHED:ESTABLISHED

기본적으로 전화하기 전에 column -tTCP 상태 "ESTABLISHED:ESTABLISHED"를 첫 번째와 세 번째 행으로 더 이동하여 두 번째 행에 올바르게 배치되도록 하고 싶습니다. 어떻게 해야 하나요? 여기서 awk와 printf를 사용하는 것은 약간 혼란스러워 보입니다. 기본적으로 모든 열을 정렬하고 마지막 열만 오른쪽 정렬하고 싶습니다.

답변1

편집 1:

한 가지 접근 방식은 다음과 같습니다.

getStats | grep ESTABLISHED | column -t | sed \
-e 's/\(<-\|->\)[ ]\+/\1 /g' \
-e 's/[ ]\+\([^ ]\+$\)/\t\1/' | column -t -s "   "
                                               ^--- TAB
all  tcp  117.54.56.131:80     <- 10.42.100.211:63752                        ESTABLISHED:ESTABLISHED
all  tcp  10.42.120.201:63752  -> 219.224.67.112:31180  -> 137.51.59.141:80  ESTABLISHED:ESTABLISHED
all  tcp  77.221.237.24:443    <- 10.42.100.117:59999                        ESTABLISHED:ESTABLISHED

먼저 column -t공백 뒤의 모든 연속 공백을 제거한 다음 마지막 열을 분리하고 새로운 작업을 수행하십시오.<-->tabcolumn -t -s '<TAB>'

명령줄에 있는 경우: -s" Ctrl+VTAB" (일명 tab) as 선택적으로 공백을 탭으로 바꿀 column수 있습니다 .tr

sed작업으로 설정 하고 건너뛰기 grep및 기타 수정 사항:

getStats | column -t | \
sed '/ESTABLISHED/!d;s/\(<-\|->\) */\1  /g;s/ *\([^ ]*\)$/\t \1/' | \
column -t -s "    "
                ^--- TAB

편집 2:

awk헷갈 리시더라도 printf옵션으로 남겨두겠습니다. 이 스크립트를 사용하면 다음과 같이 말할 수 있습니다.

getStats | scrip_name ESTABLISHED

유연한 맞춤 설정 등이 가능한 것도 장점 중 하나입니다.

어느 쪽이든 데이터를 두 번 구문 분석하거나 데이터에 대한 메타데이터를 저장하고 마지막에 인쇄합니다.

간단히 말해서, 이것이 하는 일은 다음과 같습니다:

  • 각 열의 최대 너비를 기록합니다.
  • 최대 열 수를 기록합니다.
  • 각 필드를 행별로 배열에 저장합니다.
  • 각 필드를 마지막에 인쇄하되 끝에 열의 최대 너비를 사용하십시오.
  • 채우기최대 열 수 - 1공백이 있습니다.
  • 마지막 필드를 인쇄합니다.

(코드와 나머지 코드 사이의 분할은 awk -v pat="$1" '이 페이지의 사용자 정의 강조 표시 HTML 주석으로 인한 것입니다.)

#!/bin/bash

# Argument 1 is what to match against.
awk -v pat="$1" '
# Iff match pat.
$0 ~ pat {
    # Highest number of columns.
    if (NF > cols)
        cols = NF
    # Increment number of lines.
    ++nl
    # Number of fileds on this line.
    lines[nl] = NF

    for (i = 1; i <= NF; ++i) {
        # IFF not last field and 
        # width of field is > current width of column, store it in wc_a.
        if (i < NF && (wc = length($i)) > wc_a[i])
            wc_a[i] = wc
        # Save columns in array lines[LINE COLUMN]=FIELD_DATA.
        lines[nl,i] = $i
    }
}

END {
    # Loop lines.
    for (i = 1; i <= nl; ++i) {
        # Print all but last.
        for (j = 1; j < lines[i]; ++j)
            printf("%-*s ", wc_a[j], lines[i,j])
        # Print "missing" columns.
        for (; j < cols; ++j)
            printf("%-*s ", wc_a[j], "")
        # Print last column field.
        printf("%s\n", lines[i,lines[i]])
    }
}
' "$2"
# $2 is either file or empty: expect pipe.

오래된:

삭제되었으며 여기에서 찾을 수 있습니다.

답변2

여기서 진짜 질문은열 수가 동일하지 않습니다.. 일부 행에는 6개의 열이 있고 일부 행에는 8개의 열이 있습니다.

따라서 해야 할 일은 누락된 x 및 y 필드에 빈 필드를 추가하는 것입니다(x 및 y는 5와 6 또는 3과 4일 수 있음).

다음을 수행할 수 있습니다.

F="\\(\\S\\S*\\)\\s*\\s"
# This is 0160, a nonbreaking space
G=" "

| sed -e "s/^$F$F$F$F$F$F*$/\\1 \\2 \\3 \\4 \\5 $G $G \\6/g" \
| column -t

sed6개 필드만 있는 행을 식별하고 적절한 경우 2개 추가 필드를 추가합니다. 위와 같이 나는 얻는다.

all  tcp  117.54.56.131:80     <-  10.42.100.211:63752                         ESTABLISHED:ESTABLISHED
all  tcp  10.42.120.201:63752  ->  219.224.67.112:31180  ->  137.51.59.141:80  ESTABLISHED:ESTABLISHED
all  tcp  77.221.237.24:443    <-  10.42.100.117:59999                         ESTABLISHED:ESTABLISHED

답변3

원하는 작업을 수행하는 Perl 스크립트는 다음과 같습니다.

$ getStats | grep ESTABLISHED | \
perl -ne '
chomp @a;
@a = split(" ",$_);
map { print "$_," } @a[0..4];
if ($a[5] !~ m/>/) {
  map { print " , ,$_," } @a[5..$#a];
  print "\n";
} else {
  map { print "$_," } @a[5..$#a];
  print "\n";
}
' | column -t -s ','

결과는 다음과 같습니다.

all  tcp  117.54.56.131:80     <-  10.42.100.211:63752                         ESTABLISHED:ESTABLISHED
all  tcp  10.42.120.201:63752  ->  219.224.67.112:31180  ->  137.51.59.141:80  ESTABLISHED:ESTABLISHED
all  tcp  77.221.237.24:443    <-  10.42.100.117:59999                         ESTABLISHED:ESTABLISHED

나는 귀하의 접근 방식에 대해 약간 다른 접근 방식을 취하고 column -tPerl 출력을 수정하여 각 필드 사이에 쉼표 ","를 도입했습니다. 따라서 `column 명령 이전의 출력은 다음과 같습니다.

all,tcp,117.54.56.131:80,<-,10.42.100.211:63752, , ,ESTABLISHED:ESTABLISHED,
all,tcp,10.42.120.201:63752,->,219.224.67.112:31180,->,137.51.59.141:80,ESTABLISHED:ESTABLISHED,
all,tcp,77.221.237.24:443,<-,10.42.100.117:59999, , ,ESTABLISHED:ESTABLISHED,

그런 다음 구분 기호에 대한 분할을 column -t -s ','유도하는데 column, 이는 단순한 공백보다 처리하기가 더 쉽습니다.

한 줄에 쉼표를 도입하는 것은 나에게는 다소 구식이지만 이 방법은 제 역할을 합니다. 더 단순화할 수도 있지만 실행 가능한 솔루션입니다.

관련 정보