Saya ingin menyediakan file konfigurasi terstruktur yang semudah mungkin untuk diedit oleh pengguna non-teknis (sayangnya itu harus berupa file) dan jadi saya ingin menggunakan YAML. Saya tidak dapat menemukan cara untuk menguraikan ini dari skrip shell Unix.
192
yq
untuk membaca / menulis file yaml di shell. Halaman proyek ada di sini: mikefarah.github.io/yq Anda dapat menginstal alat denganbrew
,apt
atau mengunduh biner. Membaca nilai sesederhanayq r some.yaml key.value
Jawaban:
Kasing penggunaan saya mungkin atau mungkin tidak persis sama dengan apa yang ditanyakan oleh posting asli ini, tetapi pasti mirip.
Saya perlu menarik beberapa YAML sebagai variabel bash. YAML tidak akan pernah lebih dari satu level.
YAML terlihat seperti ini:
Output like-a dis:
Saya mencapai output dengan baris ini:
s/:[^:\/\/]/="/g
menemukan:
dan menggantinya dengan="
, sementara mengabaikan://
(untuk URL)s/$/"/g
ditambahkan"
ke akhir setiap bariss/ *=/=/g
menghapus semua spasi sebelumnya=
sumber
{KEY: 'value', ...}
; dan mungkin yang lainnya. Yang paling penting, jika Anda berniat mengevaluasi hasilnya sebagai kode shell, itu akan sangat tidak aman.Berikut ini adalah pengurai bash-only yang memanfaatkan sed dan awk untuk mengurai file yaml sederhana:
Ini memahami file seperti:
Yang mana, ketika diuraikan menggunakan:
akan menampilkan:
ia juga memahami file yaml, dihasilkan oleh ruby yang mungkin menyertakan simbol ruby, seperti:
dan akan menampilkan yang sama seperti pada contoh sebelumnya.
penggunaan khas dalam skrip adalah:
parse_yaml menerima argumen awalan sehingga pengaturan yang diimpor semua memiliki awalan umum (yang akan mengurangi risiko tabrakan namespace).
hasil:
Perhatikan bahwa pengaturan sebelumnya dalam file dapat dirujuk dengan pengaturan selanjutnya:
Penggunaan bagus lainnya adalah mem-parsing file default terlebih dahulu dan kemudian pengaturan pengguna, yang berfungsi karena pengaturan yang terakhir menimpa yang pertama:
sumber
-
notasi yaml menjadi bash array asli juga!global__debug
bukanglobal_debug
.Saya telah menulis
shyaml
dengan python untuk kebutuhan permintaan YAML dari baris perintah shell.Gambaran:
File YAML contoh (dengan fitur kompleks):
Permintaan dasar:
Permintaan perulangan yang lebih kompleks pada nilai-nilai kompleks:
Beberapa poin kunci:
\0
output empuk tersedia untuk manipulasi entri multiline padat.subvalue.maintainer
adalah kunci yang valid).subvalue.things.-1
adalah elemen terakhir darisubvalue.things
urutan.)Lebih banyak sampel dan dokumentasi tersedia di halaman shyaml github atau halaman shyaml PyPI .
sumber
cat docker-compose.yml | shyaml get-value api.environment | grep -v null | awk -F': ' '{print $2 > ("envdir/" $1)}'
shyaml
sangat lambat( https://github.com/mikefarah/yq#readme )
Sebagai contoh (dicuri langsung dari dokumentasi ), diberikan file sample.yaml dari:
kemudian
akan menampilkan
sumber
Dimungkinkan untuk mengirimkan skrip kecil ke beberapa penerjemah, seperti Python. Cara mudah untuk melakukannya menggunakan Ruby dan pustaka YAML-nya adalah sebagai berikut:
, di mana
data
hash (atau array) dengan nilai-nilai dari yaml.Sebagai bonus, itu akan mengurai masalah depan Jekyll baik-baik saja.
sumber
RUBY_SCRIPT
variabel adalah script ruby yang dapat ditulis ke file bukan (run denganruby -ryaml <rubyscript_filename>
). Ini berisi logika untuk mengubah teks input menjadi beberapa teks output, secara internal menyimpan konten ke dalamdata
variabel. Gema menghasilkan teks yaml, tetapi Anda dapat menggunakancat <yaml_filename>
untuk mem-pipe konten file sebagai gantinya.stdout
dimasukkan ke dalam variabel, Anda tidak harus bergantung pada file sementara! gunakanx=$(...)
atau bahkanread a b c < <(...)
). Jadi, ini adalah solusi yang valid ketika Anda tahu persis apa yang ingin Anda ambil dalam file YAML dan tahu cara menulis garis ruby untuk mengakses data ini. Bahkan jika itu kasar, itu adalah bukti konsep konsep IMHO. Memang benar bahwa itu tidak memberi Anda abstraksi bash penuh.Mengingat bahwa Python3 dan PyYAML adalah dependensi yang cukup mudah untuk dipenuhi saat ini, berikut ini dapat membantu:
sumber
yaml.safe_load
karena lebih aman. pyyaml.org/wiki/PyYAMLDocumentationdi sini versi lanjutan dari jawaban Stefan Farestam:
Versi ini mendukung
-
notasi dan notasi singkat untuk kamus dan daftar. Input berikut:menghasilkan output ini:
karena Anda dapat melihat
-
item secara otomatis diberi nomor untuk mendapatkan nama variabel yang berbeda untuk setiap item. Dibash
sana tidak ada array multidimensi, jadi ini adalah salah satu cara untuk mengatasinya. Beberapa level didukung. Untuk mengatasi masalah dengan membuntuti spasi putih yang disebutkan oleh @briceburg, seseorang harus menyertakan nilai dalam tanda kutip tunggal atau ganda. Namun, masih ada beberapa batasan: Perluasan kamus dan daftar dapat menghasilkan hasil yang salah ketika nilai mengandung koma. Juga, struktur yang lebih kompleks seperti nilai yang mencakup banyak garis (seperti kunci ssh) belum didukung.Beberapa kata tentang kode:
sed
Perintah pertama memperluas bentuk kamus singkat{ key: value, ...}
menjadi reguler dan mengubahnya menjadi gaya yaml yang lebih sederhana.sed
Panggilan kedua melakukan hal yang sama untuk notasi singkat daftar dan mengkonversi[ entry, ... ]
ke daftar item dengan-
notasi.sed
Panggilan ketiga adalah yang asli yang menangani kamus normal, sekarang dengan tambahan untuk menangani daftar-
dan lekukan. Bagian iniawk
memperkenalkan indeks untuk setiap tingkat lekukan dan meningkatkannya ketika nama variabel kosong (yaitu saat memproses daftar). Nilai saat ini dari penghitung digunakan sebagai ganti vname kosong. Saat naik satu tingkat, penghitungnya akan memusatkan perhatian.Sunting: Saya telah membuat repositori github untuk ini.
sumber
Sulit dikatakan karena itu tergantung pada apa yang Anda ingin parser untuk mengekstrak dari dokumen YAML Anda. Untuk kasus sederhana, Anda mungkin dapat menggunakan
grep
,cut
,awk
dll Untuk lebih parsing kompleks Anda akan perlu menggunakan full-blown parsing perpustakaan seperti Python PyYAML atau YAML :: Perl .sumber
Saya baru saja menulis parser yang saya sebut Yay! ( Yaml bukan Yamlesque! ) Yang mem-parsing Yamlesque , sebagian kecil dari YAML. Jadi, jika Anda mencari parser YAML yang 100% sesuai untuk Bash maka ini bukan. Namun, untuk mengutip OP, jika Anda ingin file konfigurasi terstruktur yang semudah mungkin untuk pengguna non-teknis untuk mengedit yang seperti YAML, ini mungkin menarik.
Itu diinspirasi oleh jawaban sebelumnya tetapi menulis array asosiatif ( ya, ini membutuhkan Bash 4.x ) bukan variabel dasar. Ia melakukannya dengan cara yang memungkinkan data diurai tanpa pengetahuan sebelumnya tentang kunci sehingga kode yang digerakkan oleh data dapat ditulis.
Selain elemen array kunci / nilai, setiap array memiliki
keys
array yang berisi daftar nama kunci,children
array yang berisi nama array anak danparent
kunci yang merujuk ke induknya.Ini adalah contoh dari Yamlesque:
Berikut adalah contoh yang menunjukkan cara menggunakannya:
yang keluaran:
Dan di sini adalah pengurai:
Ada beberapa dokumentasi dalam file sumber tertaut dan di bawah ini adalah penjelasan singkat tentang apa yang kode lakukan.
The
yay_parse
Fungsi pertama menempatkaninput
file atau keluar dengan status keluar dari 1. Berikutnya, menentukan datasetprefix
, baik secara eksplisit ditentukan atau berasal dari nama file.Ini menulis
bash
perintah yang valid untuk output standar yang, jika dijalankan, menentukan array yang mewakili konten file data input. Yang pertama dari ini mendefinisikan array tingkat atas:Perhatikan bahwa deklarasi array adalah asosiatif (
-A
) yang merupakan fitur dari Bash versi 4. Deklarasi juga global (-g
) sehingga dapat dieksekusi dalam suatu fungsi tetapi tersedia untuk lingkup global sepertiyay
helper:Data input awalnya diproses dengan
sed
. Ini menghapus garis yang tidak cocok dengan spesifikasi format Yamlesque sebelum membatasi bidang Yamlesque yang valid dengan karakter Pemisah File ASCII dan menghapus tanda kutip ganda di sekitar bidang nilai.Kedua ungkapan itu serupa; mereka berbeda hanya karena yang pertama mengambil nilai yang dikutip sedangkan yang kedua memilih yang tidak dikutip.
The Berkas Separator (28 / hex 12 / oktal 034) digunakan karena, sebagai karakter non-printable, itu tidak mungkin dalam data masukan.
Hasilnya disalurkan ke
awk
mana memproses inputnya satu baris pada satu waktu. Ini menggunakan karakter FS untuk menetapkan setiap bidang ke variabel:Semua baris memiliki indent (mungkin nol) dan kunci tetapi mereka tidak semua memiliki nilai. Ini menghitung tingkat indentasi untuk garis yang membagi panjang bidang pertama, yang berisi spasi putih terkemuka, sebanyak dua. Item tingkat atas tanpa indentasi berada pada level indent nol.
Selanjutnya, ia mengetahui apa yang
prefix
harus digunakan untuk item saat ini. Inilah yang akan ditambahkan ke nama kunci untuk membuat nama array. Ada untukroot_prefix
larik level atas yang didefinisikan sebagai nama kumpulan data dan garis bawah:Ini
parent_key
adalah kunci pada level indent di atas level indentasi baris saat ini dan mewakili koleksi yang menjadi bagian dari baris saat ini. Pasangan kunci / nilai koleksi akan disimpan dalam array dengan namanya didefinisikan sebagai gabungan dariprefix
danparent_key
.Untuk tingkat atas (tingkat indentasi nol) awalan kumpulan data digunakan sebagai kunci induk sehingga tidak memiliki awalan (diatur ke
""
). Semua array lainnya diawali dengan awalan root.Selanjutnya, kunci saat ini dimasukkan ke dalam array (awk-internal) yang berisi kunci. Array ini tetap ada sepanjang seluruh sesi awk dan karenanya berisi kunci yang dimasukkan oleh baris sebelumnya. Kunci tersebut dimasukkan ke dalam array menggunakan indentasinya sebagai indeks array.
Karena array ini berisi kunci dari baris sebelumnya, kunci apa pun dengan parutan level indentasi dari level indentasi baris saat ini dihapus:
Ini meninggalkan array kunci yang berisi gantungan kunci dari root pada level indent 0 ke baris saat ini. Ini menghapus kunci basi yang tersisa ketika baris sebelumnya indentasi lebih dalam dari garis saat ini.
Bagian terakhir menampilkan
bash
perintah: baris input tanpa nilai memulai level indent baru ( koleksi dalam bahasa YAML) dan baris input dengan nilai menambahkan kunci ke koleksi saat ini.Nama koleksi adalah gabungan dari baris saat ini
prefix
danparent_key
.Ketika kunci memiliki nilai, kunci dengan nilai itu ditetapkan untuk koleksi saat ini seperti ini:
Pernyataan pertama menghasilkan perintah untuk menetapkan nilai ke elemen array asosiatif yang dinamai setelah kunci dan yang kedua mengeluarkan perintah untuk menambahkan kunci ke
keys
daftar dibatasi-ruang koleksi :Ketika kunci tidak memiliki nilai, koleksi baru dimulai seperti ini:
Pernyataan pertama menghasilkan perintah untuk menambahkan koleksi baru ke
children
daftar terbatas-ruang koleksi saat ini dan yang kedua menampilkan perintah untuk mendeklarasikan array asosiatif baru untuk koleksi baru:Semua output dari
yay_parse
dapat diurai sebagai perintah bash oleh perintah basheval
atausource
built-in.sumber
examples
danusr/lib
direktori, Ini terkait dalam jawaban saya untuk pertanyaan itu. Jika ada minat saya bisa memecahnya menjadi repo sendiri.sumber
Pilihan lain adalah mengonversi YAML ke JSON, kemudian menggunakan jq untuk berinteraksi dengan representasi JSON baik untuk mengekstrak informasi darinya atau mengeditnya.
Saya menulis skrip bash sederhana yang berisi lem ini - lihat proyek Y2J di GitHub
sumber
Jika Anda membutuhkan nilai tunggal, Anda bisa menggunakan alat yang mengubah dokumen YAML Anda menjadi JSON dan memberi makan
jq
, misalnyayq
.Isi dari sampel. Yaml:
Contoh:
sumber
Saya tahu ini sangat spesifik, tetapi saya pikir jawaban saya dapat bermanfaat bagi pengguna tertentu.
Jika Anda memiliki
node
dannpm
menginstal pada mesin Anda, Anda dapat menggunakanjs-yaml
.Instal pertama:
lalu di skrip bash Anda
Juga jika Anda menggunakan
jq
Anda dapat melakukan sesuatu seperti ituKarena
js-yaml
mengkonversi file yaml ke string json literal. Anda kemudian dapat menggunakan string dengan parser json di sistem unix Anda.sumber
Jika Anda memiliki python 2 dan PyYAML, Anda dapat menggunakan parser ini yang saya tulis disebut parse_yaml.py . Beberapa hal yang lebih rapi yang dilakukannya adalah membiarkan Anda memilih awalan (jika Anda memiliki lebih dari satu file dengan variabel yang sama) dan untuk mengambil nilai tunggal dari file yaml.
Sebagai contoh jika Anda memiliki file yaml ini:
staging.yaml:
prod.yaml:
Anda dapat memuat keduanya tanpa konflik.
Dan bahkan cherry memilih nilai yang Anda inginkan.
sumber
Anda bisa menggunakan setara dengan yq yang ditulis dalam golang:
pengembalian:
sumber
Anda juga dapat mempertimbangkan menggunakan Grunt (Pelari Tugas JavaScript). Dapat dengan mudah diintegrasikan dengan shell. Ini mendukung pembacaan YAML (
grunt.file.readYAML
) dan JSON (grunt.file.readJSON
file ).Ini dapat dicapai dengan membuat tugas di
Gruntfile.js
(atauGruntfile.coffee
), misalnya:kemudian dari shell cukup jalankan
grunt foo
(periksagrunt --help
tugas yang tersedia).Lebih jauh lagi, Anda dapat mengimplementasikan
exec:foo
tugas (grunt-exec
) dengan variabel input yang lulus dari tugas Anda (foo: { cmd: 'echo bar <%= foo %>' }
) untuk mencetak output dalam format apa pun yang Anda inginkan, kemudian menyalurkannya ke perintah lain.Ada juga alat yang mirip dengan Grunt, itu disebut gulp dengan tambahan plugin gulp-yaml .
Instal melalui:
npm install --save-dev gulp-yaml
Penggunaan sampel:
Untuk lebih banyak opsi untuk berurusan dengan format YAML , periksa situs YAML untuk proyek, perpustakaan, dan sumber daya lain yang tersedia yang dapat membantu Anda untuk mem-parsing format itu.
Alat lainnya:
Jshon
sumber
Saya tahu jawaban saya spesifik, tetapi jika seseorang sudah menginstal PHP dan Symfony , akan sangat berguna untuk menggunakan parser YAML milik Symfony.
Misalnya:
Di sini saya hanya digunakan
var_dump
untuk menampilkan parsing array tetapi tentu saja Anda dapat melakukan lebih banyak lagi ... :)sumber