행을 열로 변환


10

하이퍼 바이저에서 실행되는 VM에 대한 세부 정보가 포함 된 파일이 있습니다. 명령을 실행하고 출력을 파일로 리디렉션합니다. 그리고 아래 형식으로 사용 가능한 데이터입니다.

Virtual Machine : OL6U5
        ID     : 0004fb00000600003da8ce6948c441bb
        Status : Running
        Memory : 65536
        Uptime : 17835 Minutes
        Server : MyOVS1.vmorld.com
        Pool   : HA-POOL
        HA Mode: false
        VCPU   : 16
        Type   : Xen PVM
        OS     : Oracle Linux 6
Virtual Machine : OL6U6
        ID     : 0004fb00000600003da8ce6948c441bc
        Status : Running
        Memory : 65536
        Uptime : 17565 Minutes
        Server : MyOVS2.vmorld.com
        Pool   : NON-HA-POOL
        HA Mode: false
        VCPU   : 16
        Type   : Xen PVM
        OS     : Oracle Linux 6
Virtual Machine : OL6U7
        ID     : 0004fb00000600003da8ce6948c441bd
        Status : Running
        Memory : 65536
        Uptime : 17835 Minutes
        Server : MyOVS1.vmorld.com
        Pool   : HA-POOL
        HA Mode: false
        VCPU   : 16
        Type   : Xen PVM
        OS     : Oracle Linux 6

일부 하이퍼 바이저에서는 50 + vms를 실행하므로이 출력은 하이퍼 바이저와 다릅니다. 위 파일은 3 개의 VM 만 실행하는 하이퍼 바이저의 예일 뿐이므로 리디렉션 된 파일에는 여러 개의 N 개의 VM에 대한 정보가 포함될 것으로 예상됩니다.

awk / sed를 사용하거나 쉘 스크립트를 사용하여이 세부 정보를 아래 형식으로 가져와야합니다.

Virtual_Machine  ID                                Status   Memory  Uptime  Server              Pool        HA     VCPU  Type     OS
OL6U5            0004fb00000600003da8ce6948c441bb  Running  65536   17835   MyOVS1.vmworld.com  HA-POOL     false  16    Xen PVM  Oracle Linux 6
OL6U6            0004fb00000600003da8ce6948c441bc  Running  65536   17565   MyOVS2.vmworld.com  NON-HA-POOL     false  16    Xen PVM  Oracle Linux 6
OL6U5            0004fb00000600003da8ce6948c441bd  Running  65536   17835   MyOVS1.vmworld.com  HA-POOL     false  16    Xen PVM  Oracle Linux 6

답변:


1

파일을 두 번 걷는 것이 (큰) 문제가 아닌 경우 (메모리에 한 줄만 저장) :

awk -F : '{printf("%s\t ", $1)}' infile
echo
awk -F : '{printf("%s\t ", $2)}' infile

일반적인 필드 수는 다음과 같습니다 (파일을 많이 걸을 수 있음).

#!/bin/bash
rowcount=2
for (( i=1; i<=rowcount; i++ )); do
    awk -v i="$i" -F : '{printf("%s\t ", $i)}' infile
    echo
done

그러나 실제로 일반적인 전치의 경우 다음과 같이 작동합니다.

awk '$0!~/^$/{    i++;
                  split($0,arr,":");
                  for (j in arr) {
                      out[i,j]=arr[j];
                      if (maxr<j){ maxr=j} # max number of output rows.
                  }
            }
    END {
        maxc=i                             # max number of output columns.
        for     (j=1; j<=maxr; j++) {
            for (i=1; i<=maxc; i++) {
                printf( "%s\t", out[i,j])  # out field separator.
            }
            printf( "%s\n","" )
        }
    }' infile

그리고 그것을 예쁘게 만들기 위해 ( \t필드 구분자로 탭 사용 ) :

./script | |column -t -s $'\t'

Virtual_Machine  ID                                Status   Memory  Uptime  Server              Pool     HA     VCPU  Type     OS
OL6U7            0004fb00000600003da8ce6948c441bd  Running  65536   17103   MyOVS1.vmworld.com  HA-POOL  false  16    Xen PVM  Oracle Linux 6

일반 조옮김에 대한 위의 코드는 전체 행렬을 메모리에 저장합니다.
실제로 큰 파일에는 문제가 될 수 있습니다.


새 텍스트를 업데이트하십시오.

질문에 게시 된 새 텍스트를 처리하려면 두 가지 awk 패스가 가장 좋은 답변 인 것 같습니다. 필드가 존재하는 한 번의 패스는 헤더 필드 제목을 인쇄합니다. 다음 awk 패스는 필드 2 만 인쇄합니다. 두 경우 모두 선행 및 후행 공백을 제거하는 방법을 추가했습니다 (더 나은 형식화).

#!/bin/bash
{
awk -F: 'BEGIN{ sl="Virtual Machine"}
         $1~sl && head == 1 { head=0; exit 0}
         $1~sl && head == 0 { head=1; }
         head == 1 {
             gsub(/^[ \t]+/,"",$1);   # remove leading  spaces
             gsub(/[ \t]+$/,"",$1);   # remove trailing spaces
             printf( "%s\t", $1)
         }
         ' infile
#echo
awk -F: 'BEGIN { sl="Virtual Machine"}
         $1~sl { printf( "%s\n", "") }
         {
             gsub(/^[ \t]+/,"",$2);   # remove leading  spaces
             gsub(/[ \t]+$/,"",$2);   # remove trailing spaces
             printf( "%s\t", $2)
         }
         ' infile
echo
} | column -t -s "$(printf '%b' '\t')"

주변 { ... } | column -t -s "$(printf '%b' '\t')"은 전체 테이블을 예쁜 방식으로 형식화합니다.
이 있습니다 "$(printf '%b' '\t')"로 대체 될 수 $'\t'KSH, 배쉬, 또는 zsh을에.


8

당신이있는 경우 rs(모양 변경) 유틸리티를 사용할 수, 다음을 수행 할 수 있습니다 :

rs -Tzc: < input.txt

그러면 동적 열 너비까지도 질문에 지정된대로 정확하게 출력 형식이 제공됩니다.

  • -T 입력 데이터를 바꿉니다
  • -z 각 열의 최대 값에서 열의 크기를 적절하게 조정합니다.
  • -c: 입력 필드 구분자로 콜론 사용

이것은 임의의 크기의 테이블에서 작동합니다. 예 :

$ echo "Name:Alice:Bob:Carol
Age:12:34:56
Eyecolour:Brown:Black:Blue" | rs -Tzc: 
Name   Age  Eyecolour
Alice  12   Brown
Bob    34   Black
Carol  56   Blue
$ 

rsOS X (및 다른 BSD 시스템)에서 기본적으로 사용 가능합니다. Ubuntu (및 데비안 제품군)에 다음을 사용하여 설치할 수 있습니다.

sudo apt-get install rs

6

편집 : 간단한 단일 라이너 for루프 에서 여러 출력 행으로 확장 가능합니다 .

for ((i=1;i<=2;i++)); do cut -d: -f "$i" input | paste -sd: ; done | column -t -s:

원래 답변 :

bash프로세스 대체를 사용하여 단일 라이너로이를 수행 할 수 있습니다 .

paste -sd: <(cut -d: -f1 input) <(cut -d: -f2 input) | column -t -s:

-s에 옵션 paste은 한 번에 각 파일을 처리 할 수 있습니다. :의 구분 세트 paste에 의해 "잡힌"있는 -s에 옵션 column필드를하여 꽤 최대 형식으로, 마지막에 일렬로.

cut두 프로세스 대체 의 명령은 각각 첫 번째 필드와 두 번째 필드를 가져옵니다.

입력에 빈 줄이 있는지 여부는 중요하지 않습니다 column -t -s:. 출력에 관계없이 출력을 정리합니다. (질문에 지정된 원래 입력에 빈 줄이 있었지만 이후 제거되었습니다. 위 명령은 빈 줄에 관계없이 작동합니다.)

입력-위 명령에서 "input"이라는 파일의 내용 :

Virtual_Machine:OL6U7

ID:0004fb00000600003da8ce6948c441bd

Status:Running

Memory:65536

Uptime:17103

Server:MyOVS1.vmworld.com

Pool:HA-POOL

HA:false

VCPU:16

Type:Xen PVM

OS:Oracle Linux 6

산출:

Virtual_Machine  ID                                Status   Memory  Uptime  Server              Pool     HA     VCPU  Type     OS
OL6U7            0004fb00000600003da8ce6948c441bd  Running  65536   17103   MyOVS1.vmworld.com  HA-POOL  false  16    Xen PVM  Oracle Linux 6

2
이것은 두 개의 출력 행에서 작동하지만 더 많은 행에서는 작동하지 않습니다.

2

awk를 사용하여 키와 값을 저장하고 마지막에 인쇄하십시오.

#!/usr/bin/awk -f
BEGIN {
  CNT=0
  FS=":"
}

{
  HDR[CNT]=$1;
  ENTRY[CNT]=$2;
  CNT++;
}

END {
  for (x = 0; x < CNT; x++)
    printf "%s\t",HDR[x]

  print""

  for (x = 0; x < CNT; x++)
    printf "%s\t",ENTRY[x]
  }

방금 실행 awk -f ./script.awk ./input.txt


답변을 동적으로 변경했습니다. 파일 당 1 개의 VM 가치 데이터 만 있으면됩니다.
jecxjo

1
declare -a COLS
declare -a DATA
while IFS=':' read -ra fields; do
   COLS+=("${fields[0]}")
   DATA+=("${fields[1]}")
done < <( cat /path/to/input.txt)

HEADER=""
DATA=""
for i in $(seq 0 $((${#fields[@]}-1)); do
    HEADER="${HEADER}${COLS[$i]} "
    DATA="${DATA}${COLS[$i]} "
done
echo $HEADER
echo $DATA

1

gnu datamashcolumn에서 util-linux:

datamash -t: transpose <infile | column -t -s:

이것은 두 개 이상의 열에서 작동하지만 입력 파일에 빈 줄이 없다고 가정합니다. 사이에 빈 줄이 있으면 (초기 입력 샘플과 같이) 다음과 같은 오류가 발생합니다.

datamash: transpose input error: line 2 has 0 fields (previous lines had 2);

따라서 처리하기 전에 압착해야합니다 datamash.

tr -s \\n <infile | datamash -t: transpose | column -t -s:

그렇지 않으면이 특별한 경우 (두 열 만)와 zsh같고 column:

list=(${(f)"$(<infile)"})
printf %s\\n ${(j;:;)list[@]%:*} ${(j;:;)list[@]#*:} | column -t -s:

(${(f)"$(<infile)"})배열의 행을 읽습니다. ${(j;:;)list[@]%:*}(함께 결합 :각 요소의 첫 번째 필드) 및 ${(j;:;)list[@]#*:}(다시 결합 :) 각 요소의 두 번째 필드; 이들은 모두 인쇄됩니다. 예 : 출력은

Virtual_Machine:ID:Status:Memory:Uptime:Server:Pool:HA:VCPU:Type:OS
OL6U7:0004fb00000600003da8ce6948c441bd:Running:65536:17103:MyOVS1.vmworld.com:HA-POOL:false:16:Xen PVM:Oracle Linux 6

그런 다음 파이프 column -t -s:


0

cat <(head -n 11 virtual.txt | cut -d: -f1) <(sed 's/.*: //' virtual.txt) | xargs -d '\n' -n 11 | column -t

이 경우 가상 머신 당 라인 수는-11로 하드 코딩됩니다. 미리 계산하여 변수에 저장 한 다음이 변수를 코드에 사용하십시오.

설명

  1. cat <(command 1) <(command 2)- <()구성은 command출력을 임시 파일처럼 보이게합니다. 따라서 cat두 개의 파일을 연결하고 더 파이프합니다.

    • command 1 : head -n 11 virtual.txt | cut -d: -f1은 미래의 열 헤더를 제공합니다. 하나의 가상 머신 항목은 첫 번째 11 줄이며 head명령을 사용하여 가져옵니다. 는 cut두 개의 열이 항목을 분할하고있는 유일한 첫 번째를 인쇄 할 수 있습니다.
    • command 2 : sed 's/.*: //' virtual.txt-미래의 열 값을 제공합니다. sed불필요한 텍스트를 모두 제거하고 값만 남겨 둡니다.
  2. xargs -d '\n' -n 11. 각 입력 항목은 개행으로 종료됩니다. 이 명령은 항목을 가져 와서 한 줄에 11 씩 인쇄합니다.

  3. column -t-예쁜 인쇄 디스플레이에 필요합니다. 행을 테이블 형식으로 표시합니다. 그렇지 않으면 각 줄의 너비가 달라집니다.

산출

Virtual  Machine                           ID       Status  Memory  Uptime   Server             Pool         HA     Mode  VCPU  Type  OS
OL6U5    0004fb00000600003da8ce6948c441bb  Running  65536   17835   Minutes  MyOVS1.vmorld.com  HA-POOL      false  16    Xen   PVM   Oracle  Linux  6
OL6U6    0004fb00000600003da8ce6948c441bc  Running  65536   17565   Minutes  MyOVS2.vmorld.com  NON-HA-POOL  false  16    Xen   PVM   Oracle  Linux  6
OL6U7    0004fb00000600003da8ce6948c441bd  Running  65536   17835   Minutes  MyOVS1.vmorld.com  HA-POOL      false  16    Xen   PVM   Oracle  Linux  6

0

파일에서 행과 열을 바꾸려면 datamash및 해당 transpose옵션을 사용하십시오 .

datamash -t: transpose < infile.txt

기본적으로 transpose는 입력에 각 줄에 동일한 수의 필드가 있는지 확인하고 그렇지 않으면 오류로 실패하고 엄격한 모드를 비활성화하여 다음과 같이 누락 된 값을 허용 할 수 있습니다 --no-strict

datamash -t: --no-strict transpose < infile.txt

또한 --filler누락 필드 필러 값을 설정하는 데 사용할 수 있습니다 .

datamash -t: --no-strict --filler " " transpose < infile.txt

로부터 나오다 datamash manual


-5

데이터가 디렉토리의 별도 파일에 있으면 다음을 사용할 수 있습니다.

for file in $(ls $DIRECTORY)
do
  cat ${file} | while read line
  do
    value=$(echo $line | cut -d: -f2-)
    printf "%s\t" "${value}" >> bigfile
  done
  echo " " >> bigfile
done

변수 값의 길이가 다른 경우 줄 의 \t(탭) 문자 수를 마사지해야 할 수도 있습니다 printf.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.