아래 한 줄이 들어있는 파일이 있습니다.
{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
답변
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
]
};
답변
쉘 텍스트 처리 유틸리티는 주로 공백 또는 고정 문자로 구분 된 필드와 필드 당 하나의 레코드로 표시되는 데이터를 조작하도록 설계되었습니다. 이 형식은 완전히 다르므로 간단하게 처리 할 수 없습니다.
한 가지 방법은 쉽게 처리 할 수있는 형식 유형에 맞게 파일을 사전 처리하는 것입니다. 여기서는 괄호와 중괄호를 여기에 설명 된 것 이외의 방식으로 사용하지 않는다고 가정합니다 (전체 텍스트 주위의 괄호, 기계 값 목록 주위의 괄호).
<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
답변
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]
답변
이것은 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"
]
}