Saya ingin memberi tahu apakah string $string
akan dicocokkan dengan pola gumpalan $pattern
. $string
mungkin atau mungkin bukan nama file yang ada. Bagaimana saya bisa melakukan ini?
Asumsikan format berikut untuk string input saya:
string="/foo/bar"
pattern1="/foo/*"
pattern2="/foo/{bar,baz}"
Saya ingin menemukan idiom bash yang menentukan apakah $string
akan dicocokkan oleh $pattern1
, $pattern2
atau pola segumpal sewenang-wenang lainnya. Inilah yang saya coba sejauh ini:
[[ "$string" = $pattern ]]
Ini hampir berhasil, kecuali yang
$pattern
ditafsirkan sebagai pola string dan bukan sebagai pola glob.[ "$string" = $pattern ]
Masalah dengan pendekatan ini adalah yang
$pattern
diperluas dan kemudian perbandingan string dilakukan antara$string
dan perluasan$pattern
.[[ "$(find $pattern -print0 -maxdepth 0 2>/dev/null)" =~ "$string" ]]
Yang ini berfungsi, tetapi hanya jika
$string
berisi file yang ada.[[ $string =~ $pattern ]]
Ini tidak berfungsi karena
=~
operator menyebabkan$pattern
ditafsirkan sebagai ekspresi reguler yang diperluas, bukan pola gumpalan atau wildcard.
{bar,baz}
itu bukan pola. Ini ekspansi parameter. Perbedaan yang halus namun kritis dalam hal{bar,baz}
itu diperluas sejak awal menjadi banyak argumen,bar
danbaz
.ls /foo/*
sekarang kamu bisa mencocokkannya dalamfoo/{bar,baz}
sebenarnya adalah ekspansi brace (bukan ekspansi parameter) sementarafoo/*
ekspansi pathname.$string
adalah ekspansi parameter. Ini semua dilakukan pada waktu yang berbeda dan dengan mekanisme yang berbeda.case
pernyataan melakukan Pathname Expansion ("globbing") sesuai dengan manual Bash.Jawaban:
Tidak ada solusi umum untuk masalah ini. Alasannya adalah bahwa, dalam bash, ekspansi brace (yaitu,
{pattern1,pattern2,...}
dan ekspansi nama file (alias pola glob) dianggap sebagai hal yang terpisah dan diperluas dalam kondisi yang berbeda dan pada waktu yang berbeda. Berikut adalah daftar lengkap ekspansi yang dilakukan bash:Karena kami hanya peduli pada subset dari ini (mungkin brace, tilde, dan ekspansi pathname), dimungkinkan untuk menggunakan pola dan mekanisme tertentu untuk membatasi ekspansi dengan cara yang terkendali. Contohnya:
Menjalankan skrip ini menghasilkan output berikut:
Ini berfungsi karena
set -f
menonaktifkan ekspansi pathname, jadi hanya ekspansi brace dan ekspansi tilde terjadi dalam pernyataanfor pattern in /foo/{*,foo*,bar*,**,**/*}
. Kita kemudian dapat menggunakan operasi tes[[ $string == $pattern ]]
untuk menguji terhadap ekspansi pathname setelah ekspansi brace telah dilakukan.sumber
Saya tidak percaya itu
{bar,baz}
adalah pola glob shell (meskipun tentu saja/foo/ba[rz]
) tetapi jika Anda ingin tahu apakah$string
cocok$pattern
Anda bisa melakukannya:Anda dapat melakukan sebanyak yang Anda suka:
sumber
{bar,baz}
bukan pola gumpalan. Saya sudah menemukan solusi untuk pertanyaan saya yang memperhitungkan hal ini.Seperti yang ditunjukkan Patrick, Anda membutuhkan "jenis pola" yang berbeda:
Kutipan tidak diperlukan di sana.
sumber
sed
operasi sederhana .Saya akan menggunakan grep dengan demikian:
Yang memberikan output:
sumber
dalam zsh:
sumber