Membagi file dan memasukkannya ke dalam struktur data yang sesuai?

10

Saya memiliki file yang berisi satu baris di bawah ini:

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

di mana saya memiliki dua set data:

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

Sekarang, saya perlu membaca file di atas dan membaginya sedemikian rupa sehingga saya dapat mengekstraksi informasi setiap mesin seperti yang disebutkan di atas dan menyimpannya dalam beberapa struktur data.

Saat ini, saya bingung struktur data mana yang harus saya gunakan dalam skrip bash shell. Jika saya melakukan ini di Jawa, saya akan menggunakan Map<String, Set<String>>tetapi saya tidak yakin apa yang harus saya gunakan dalam skrip shell.

Dan setelah menyimpannya dalam beberapa struktur data, saya perlu mengulanginya dan mencetak hasilnya.

Saya dapat membaca file di atas menggunakan skrip shell di bawah ini:

#!/bin/bash

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

Tetapi saya tidak yakin bagaimana cara membagi data garis di atas sedemikian rupa sehingga saya dapat mengekstraksi setiap informasi mesin dan kemudian menyimpannya dalam beberapa struktur data?

MEMPERBARUI:-

Di bawah ini adalah skrip shell yang saya dapatkan setelah mengikuti saran yang diberikan oleh 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
SSH
sumber

Jawaban:

4

struktur data bash terlalu sederhana bahkan untuk array 2 dimensi. Apakah Anda yakin ini alat yang ingin Anda gunakan?

Dengan bash dan GNU grep, Anda dapat melakukan kekacauan yang tidak menyenangkan ini:

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

Ini sangat rapuh. Saya akan menggunakan Perl untuk sesuatu seperti ini: masih jelek tapi lebih ringkas

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
                        ]
        };
glenn jackman
sumber
Terima kasih atas sarannya. Saya mungkin pergi dengan opsi skrip shell karena akhirnya saya harus menggunakan scp jadi saya percaya melakukan scp dalam skrip shell akan mudah. Tapi bagaimanapun, mari kita lihat bagaimana hasilnya. Saya telah memperbarui pertanyaan saya dengan skrip shell aktual yang mungkin saya gunakan setelah memasukkan saran Anda. Silakan lihat dan beri tahu saya jika terlihat benar dan jika ada yang ingin Anda modifikasi, beri tahu saya juga.
SSH
+1 Gerakan cukup apik dengan eval, di sana.
Joseph R.
1

Utilitas pemrosesan teks shell terutama dirancang untuk memanipulasi data yang diwakili dengan satu catatan per baris dan bidang yang dipisahkan oleh spasi putih, atau karakter tetap. Format ini sangat berbeda dan Anda tidak akan dapat memprosesnya secara langsung.

Salah satu pendekatan adalah preproses file agar sesuai dengan jenis format yang dapat diproses dengan mudah. Saya berasumsi bahwa tanda kurung dan kurung kurawal tidak digunakan dengan cara apa pun selain yang digambarkan di sini (tanda kurung di seluruh teks, tanda kurung di sekitar daftar nilai mesin).

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

Hasilnya memiliki satu mesin per baris dan koma untuk memisahkan catatan. Cuplikan berikut mem-parsing nama mesin pada setiap baris dan meninggalkan daftar nilai yang dipisahkan koma values.

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

Cuplikan khusus bash berikut menempatkan nilai dalam array.

 | while IFS=, read -r -a values; do
  machine=${values[0]}; shift values
  echo "There are ${#values[@]} on machine $machine"
done
Gilles 'SANGAT berhenti menjadi jahat'
sumber
@ Giles: Terima kasih atas sarannya. Apakah mungkin untuk mendapatkan jumlah total file untuk setiap mesin? artinya jumlah total menggunakan perintah di atas yang sama? Seperti, untuk contoh di atas, machineA memiliki empat file dan machineB juga memiliki empat file
SSH
@ SSH Lihat hasil edit saya.
Gilles 'SANGAT berhenti menjadi jahat'
0

Anda bisa menggunakannya awkuntuk menyelesaikan tugas.

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]
John B
sumber
John terima kasih. Apakah mungkin untuk mendapatkan jumlah total file juga untuk setiap mesin. Seperti, untuk contoh di atas, machineA memiliki empat file dan machineB juga memiliki empat file. Apakah mungkin untuk mendapatkan itu juga?
SSH
0

Ini terlihat seperti JSON. Anda bisa memperbaikinya menjadi JSON yang tepat dan menggunakan alat 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"
   ]
}
Vi.
sumber