파일을 분할하여 해당 데이터 구조에 넣습니까?


10

아래 한 줄이 들어있는 파일이 있습니다.

{machineA=[0, 1024, 4, 1028], machineB=[1, 1025, 5, 1029]}

두 개의 데이터 세트가 있습니다.

machineA=[0, 1024, 4, 1028]
machineB=[1, 1025, 5, 1029]

이제 위의 파일을 읽고 위에서 언급 한대로 각 머신의 정보를 추출하여 일부 데이터 구조에 저장할 수있는 방식으로 분할해야합니다.

현재 bash 쉘 스크립트에서 사용해야하는 데이터 구조가 혼란 스럽습니다. Java 로이 작업을 수행했다면 사용 Map<String, Set<String>>하지만 쉘 스크립트에서 무엇을 사용 해야하는지 잘 모르겠습니다.

그리고 일부 데이터 구조에 저장 한 후 반복하고 결과를 인쇄해야합니다.

아래 쉘 스크립트를 사용하여 위 파일을 읽을 수 있습니다.

#!/bin/bash

while read -r line; do
       echo "$line"
    done < data.txt

그러나 각 기계 정보를 추출한 다음 일부 데이터 구조에 저장할 수 있도록 위의 행 데이터를 분할하는 방법을 잘 모르겠습니다.

최신 정보:-

아래는 glenn의 제안을 따른 후 얻은 쉘 스크립트입니다.

#!/bin/bash

while read -r line; do
       echo "$line"
       declare -A "$(
            echo "x=("
            grep -oP '(\w+)(?==)|(?<==\[).*?(?=\])' <<< "$line" |
              tr -d , |
              paste - - |
              sed 's/^/[/; s/\t/]="/; s/$/"/'
            echo ")"
        )"

        for key in "${!x[@]}"; do           # need quotes here
            for element in ${x[$key]}; do   # no quotes here
                printf "%s\t%s\n" "$key" "$element"
            done
        done    
    done < primary.txt

답변:


4

bash 데이터 구조는 2 차원 배열에도 너무 기초적입니다. 이 도구가 사용하려는 도구입니까?

bash와 GNU grep을 사용하면 다음과 같은 불쾌한 엉망을 할 수 있습니다.

line='{machineA=[0, 1024, 4, 1028], machineB=[1, 1025, 5, 1029]}'
declare -A "$(
    echo "x=("
    grep -oP '(\w+)(?==)|(?<==\[).*?(?=\])' <<< "$line" |
      tr -d , |
      paste - - |
      sed 's/^/[/; s/\t/]="/; s/$/"/'
    echo ")"
)"

for key in "${!x[@]}"; do           # need quotes here
    for element in ${x[$key]}; do   # no quotes here
        printf "%s\t%s\n" "$key" "$element"
    done
done
machineA    0
machineA    1024
machineA    4
machineA    1028
machineB    1
machineB    1025
machineB    5
machineB    1029

이것은 아주 연약하다. 나는 Perl을 다음과 같이 사용할 것입니다 : 여전히 추악하지만 간결한

echo "$line" | perl -MData::Dumper -ne '
    s/=\[/=>[/g; 
    eval "\$x=$_";
    # do something with your data structure (a hash of arrays) 
    print Dumper($x)
'
$VAR1 = {
          'machineB' => [
                          1,
                          1025,
                          5,
                          1029
                        ],
          'machineA' => [
                          0,
                          1024,
                          4,
                          1028
                        ]
        };

제안 해 주셔서 감사합니다. 쉘 스크립트 옵션을 사용하면 마지막으로 scp를 사용해야하므로 쉘 스크립트에서 scp를 수행하는 것이 쉬울 것이라고 생각합니다. 어쨌든 이것이 어떻게 진행되는지 봅시다. 제안 사항을 통합 한 후 사용중인 실제 쉘 스크립트로 내 질문을 업데이트했습니다. 한 번 살펴보고 정확 해 보이는지 알려주고 수정하고 싶은 것이 있으면 알려주십시오.
SSH

+1이 (가 eval) 있으면 꽤 매끄러운 이동입니다 .
Joseph R.

1

쉘 텍스트 처리 유틸리티는 주로 공백 또는 고정 문자로 구분 된 필드와 필드 당 하나의 레코드로 표시되는 데이터를 조작하도록 설계되었습니다. 이 형식은 완전히 다르므로 간단하게 처리 할 수 ​​없습니다.

한 가지 방법은 쉽게 처리 할 수있는 형식 유형에 맞게 파일을 사전 처리하는 것입니다. 여기서는 괄호와 중괄호를 여기에 설명 된 것 이외의 방식으로 사용하지 않는다고 가정합니다 (전체 텍스트 주위의 괄호, 기계 값 목록 주위의 괄호).

<data.txt sed -e 's/^{//' -e 's/}$//' -e 's/ *= *\[/,/g' -e 's/, */,/g' -e 's/\] *$//' -e 's/] *, */\n/g'

결과는 한 줄에 하나의 기계와 쉼표가있어 레코드를 분리합니다. 다음 스 니펫은 각 행에서 머신 이름을 구문 분석하고에 쉼표로 구분 된 값 목록을 남깁니다 values.

 | while IFS=, read -r machine values; do 

다음 bash 특정 스 니펫은 값을 배열에 넣습니다.

 | while IFS=, read -r -a values; do
  machine=${values[0]}; shift values
  echo "There are ${#values[@]} on machine $machine"
done

@ 길리스 : 제안 주셔서 감사합니다. 각 머신의 총 파일 수를 얻을 수 있습니까? 위의 동일한 명령을 사용하여 총 수를 의미합니까? 예를 들어, machineA에는 4 개의 파일이 있고 machineB에는 4 개의 파일이 있습니다
SSH

@SSH 내 편집을 참조하십시오.
Gilles 'SO- 악한 중지

0

awk작업을 완료하는 데 사용할 수 있습니다 .

awk -F "], " '/[a-zA-Z]=\[[0-9]/ {gsub(/{|}/,""); for(i=1; i<=NF; i++) if($i !~ /\]$/) print $i"]"; else print $i}' data.txt

machineA=[0, 1024, 4, 1028]
machineB=[1, 1025, 5, 1029]

고마워 존. 각 머신의 총 파일 수를 얻을 수 있습니까? 예를 들어, machineA에는 4 개의 파일이 있고 machineB에는 4 개의 파일이 있습니다. 그것도 얻을 수 있습니까?
SSH

0

이것은 JSON과 비슷합니다. 올바른 JSON으로 수정하고 JSON 도구를 사용할 수 있습니다.

$ echo '{machineA=[0, 1024, 4, 1028], machineB=[1, 1025, 5, 1029]}' |  perl -pe 's!\b!"!g; s/=/:/g' | json_pp
{
   "machineB" : [
      "1",
      "1025",
      "5",
      "1029"
   ],
   "machineA" : [
      "0",
      "1024",
      "4",
      "1028"
   ]
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.