Alat mirip grep
yang memahami sintaksis kode sumber dan memungkinkan manipulasi selain pencarian.
Seperti grep
, ekspresi reguler adalah inti primitif. Tidak seperti grep
, kemampuan tambahan memungkinkan presisi lebih tinggi , dengan opsi manipulasi . Hal ini memungkinkan srgn
untuk beroperasi sepanjang ekspresi reguler dimensi dan perkakas IDE ( Ganti nama semua , Temukan semua referensi , ...) saja tidak bisa, melengkapinya.
srgn
diatur berdasarkan tindakan yang harus diambil (jika ada), bertindak hanya dalam cakupan tata bahasa yang tepat dan opsional. Dalam hal alat yang ada, anggap saja sebagai campuran tr
, sed
, ripgrep dan tree-sitter
, dengan tujuan desain yang sederhana : jika Anda mengetahui regex dan dasar-dasar bahasa yang Anda gunakan, Anda siap melakukannya .
Tip
Semua cuplikan kode yang ditampilkan di sini diverifikasi sebagai bagian dari pengujian unit menggunakan biner srgn
yang sebenarnya. Apa yang dipamerkan di sini dijamin berhasil.
Penggunaan srgn
paling sederhana berfungsi mirip dengan tr
:
$ echo ' Hello World! ' | srgn ' [wW]orld ' ' there ' # replacement
Hello there !
Kecocokan untuk pola ekspresi reguler '[wW]orld'
( scope ) diganti ( action ) dengan argumen posisi kedua. Nol atau lebih tindakan dapat ditentukan:
$ echo ' Hello World! ' | srgn ' [wW]orld ' # zero actions: input returned unchanged
Hello World !
$ echo ' Hello World! ' | srgn --upper ' [wW]orld ' ' you ' # two actions: replacement, afterwards uppercasing
Hello YOU !
Penggantian selalu dilakukan terlebih dahulu dan ditentukan secara posisi. Tindakan lainnya diterapkan setelahnya dan diberikan sebagai tanda baris perintah.
Demikian pula, lebih dari satu cakupan dapat ditentukan: selain pola regex, cakupan tata bahasa dapat diberikan, yang mencakup elemen sintaksis kode sumber (pikirkan, misalnya, "semua kumpulan definisi class
dalam Python" ). Jika keduanya diberikan, pola ekspresi reguler hanya diterapkan dalam lingkup bahasa pertama tersebut . Hal ini memungkinkan pencarian dan manipulasi dengan presisi yang biasanya tidak mungkin dilakukan menggunakan ekspresi reguler biasa, dan menyajikan dimensi yang berbeda dari alat seperti Ganti nama semua di IDE.
Misalnya, pertimbangkan file sumber Python (tidak ada gunanya) ini:
"""Module for watching birds and their age."""
from dataclasses import dataclass
@ dataclass
class Bird :
"""A bird!"""
name : str
age : int
def celebrate_birthday ( self ):
print ( "?" )
self . age += 1
@ classmethod
def from_egg ( egg ):
"""Create a bird from an egg."""
pass # No bird here yet!
def register_bird ( bird : Bird , db : Db ) -> None :
assert bird . age >= 0
with db . tx () as tx :
tx . insert ( bird )
yang dapat dicari menggunakan:
$ cat birds.py | srgn --python ' class ' ' age '
11: age: int
15: self.age += 1
String age
dicari dan ditemukan hanya dalam definisi class
Python (dan bukan, misalnya, dalam badan fungsi seperti register_bird
, di mana age
juga muncul dan hampir tidak mungkin untuk dikecualikan dari pertimbangan dalam vanilla grep
). Secara default, 'mode pencarian' ini juga mencetak nomor baris. Mode pencarian dimasukkan jika tidak ada tindakan yang ditentukan , dan bahasa seperti --python
diberikan 1 —anggap saja seperti 'ripgrep tetapi dengan elemen bahasa sintaksis'.
Pencarian juga dapat dilakukan lintas baris, misalnya untuk menemukan metode (alias def
dalam class
) yang tidak memiliki dokumen:
$ cat birds.py | srgn --python ' class ' ' def .+:ns+[^"s]{3} ' # do not try this pattern at home
13: def celebrate_birthday(self):
14: print("?")
Perhatikan bagaimana ini tidak muncul baik from_egg
(memiliki docstring) atau register_bird
(bukan metode, def
di luar class
).
Cakupan bahasanya sendiri juga dapat ditentukan beberapa kali. Misalnya, dalam cuplikan Rust
pub enum Genre {
Rock ( Subgenre ) ,
Jazz ,
}
const MOST_POPULAR_SUBGENRE : Subgenre = Subgenre :: Something ;
pub struct Musician {
name : String ,
genres : Vec < Subgenre > ,
}
beberapa item dapat dibor melalui pembedahan menjadi sebagai
$ cat music.rs | srgn --rust ' pub-enum ' --rust ' type-identifier ' ' Subgenre ' # AND'ed together
2: Rock(Subgenre),
di mana hanya garis yang cocok dengan semua kriteria yang dikembalikan, bertindak seperti logika dan di antara semua kondisi. Perhatikan bahwa kondisi dievaluasi dari kiri ke kanan, menghalangi beberapa kombinasi agar tidak masuk akal: misalnya, mencari isi class
Python di dalam doc-strings
Python biasanya tidak menghasilkan apa-apa. Namun kebalikannya berfungsi seperti yang diharapkan:
$ cat birds.py | srgn --py ' class ' --py ' doc-strings '
8: """A bird!"""
19: """Create a bird from an egg."""
Tidak ada dokumen di luar badan class
yang muncul!
Bendera -j
mengubah perilaku ini: dari berpotongan dari kiri ke kanan, menjadi menjalankan semua kueri secara mandiri dan menggabungkan hasilnya, sehingga Anda dapat menelusuri berbagai cara sekaligus:
$ cat birds.py | srgn -j --python ' comments ' --python ' doc-strings ' ' bird[^s] '
8: """A bird!"""
19: """Create a bird from an egg."""
20: pass # No bird here yet!
Pola bird[^s]
juga ditemukan di dalam komentar atau dokumen, bukan hanya "dokumen di dalam komentar".
Jika input standar tidak diberikan, srgn
mengetahui cara menemukan file sumber yang relevan secara otomatis, misalnya di repositori ini:
$ srgn --python ' class ' ' age '
docs/samples/birds
11: age: int
15: self.age += 1
docs/samples/birds.py
9: age: int
13: self.age += 1
Ia secara rekursif menelusuri direktorinya saat ini, menemukan file berdasarkan ekstensi file dan baris shebang, memproses dengan kecepatan sangat tinggi. Misalnya, srgn --go strings 'd+'
menemukan dan mencetak ~140.000 digit dalam string Go literal di dalam basis kode Kubernetes yang berisi ~3.000.000 baris kode Go dalam waktu 3 detik pada 12 inti M3. Untuk informasi lebih lanjut tentang bekerja dengan banyak file, lihat di bawah.
Cakupan dan tindakan dapat digabungkan hampir secara sewenang-wenang (walaupun banyak kombinasi tidak akan berguna atau bahkan tidak bermakna). Misalnya, pertimbangkan cuplikan Python ini (untuk contoh penggunaan bahasa lain yang didukung, lihat di bawah):
"""GNU module."""
def GNU_says_moo ():
"""The GNU function -> say moo -> ✅"""
GNU = """
GNU
""" # the GNU...
print ( GNU + " says moo" ) # ...says moo
yang dengannya perintah berikut dijalankan:
cat gnu.py | srgn --titlecase --python ' doc-strings ' ' (?' ' $1: GNU ? is not Unix '
Anatomi doa itu adalah:
--titlecase
(suatu tindakan) akan Judul Semuanya Ditemukan Dalam Cakupan
--python 'doc-strings'
(suatu ruang lingkup) akan mencakup (yaitu, hanya mempertimbangkan) docstrings sesuai dengan tata bahasa bahasa Python
'(? (suatu cakupan) hanya melihat apa yang telah dicakup oleh opsi sebelumnya, dan akan mempersempitnya lebih jauh. Ia tidak akan pernah bisa memperluas cakupan sebelumnya. Cakupan ekspresi reguler diterapkan setelah cakupan bahasa apa pun.
(? adalah sintaksis tampilan belakang negatif, yang menunjukkan bagaimana fitur lanjutan ini tersedia. String
GNU
yang diawali dengan The
tidak akan dipertimbangkan.
'$1: GNU ? is not Unix'
(suatu tindakan) akan menggantikan setiap kejadian yang cocok (yaitu, setiap bagian masukan yang ditemukan berada dalam cakupan) dengan string ini. Kemunculan yang cocok adalah pola '(? hanya dalam dokumen Python. Khususnya, string pengganti ini menunjukkan:
$1
, yang membawa konten yang ditangkap oleh grup regex penangkap pertama. Itu ([az]+)
, karena (? tidak menangkap.
Perintah ini menggunakan beberapa cakupan (bahasa dan pola regex) dan beberapa tindakan (penggantian dan titlecasing). Hasilnya kemudian terbaca
"""Module: GNU ? Is Not Unix."""
def GNU_says_moo ():
"""The GNU function -> say moo -> ✅"""
GNU = """
GNU
""" # the GNU...
print ( GNU + " says moo" ) # ...says moo
dimana perubahannya terbatas pada:
- """GNU module."""
+ """Module: GNU ? Is Not Unix."""
def GNU_says_moo():
"""The GNU -> say moo -> ✅"""
Peringatan
Meskipun srgn
masih dalam versi beta (versi utama 0), pastikan untuk hanya memproses file (secara rekursif) yang dapat Anda pulihkan dengan aman.
Mode pencarian tidak menimpa file, sehingga selalu aman.
Lihat di bawah untuk keluaran bantuan lengkap dari alat ini.
Catatan
Bahasa yang didukung adalah
Unduh biner bawaan dari rilis.
Peti ini menyediakan binernya dalam format yang kompatibel dengan cargo-binstall
:
cargo install cargo-binstall
(mungkin memerlukan waktu cukup lama)cargo binstall srgn
(beberapa detik, saat ia mengunduh binari bawaan dari GitHub)Langkah-langkah ini dijamin berhasil™, karena telah diuji di CI. Mereka juga berfungsi jika tidak ada biner bawaan yang tersedia untuk platform Anda, karena alat tersebut akan kembali ke kompilasi dari sumber.
Formula tersedia melalui:
brew install srgn
Tersedia melalui tidak stabil:
nix-shell -p srgn
Tersedia melalui AUR.
Tersedia port:
sudo port install srgn
Semua gambar runner GitHub Actions dilengkapi dengan cargo
yang sudah diinstal sebelumnya, dan cargo-binstall
menyediakan GitHub Action yang nyaman:
jobs :
srgn :
name : Install srgn in CI
# All three major OSes work
runs-on : ubuntu-latest
steps :
- uses : cargo-bins/cargo-binstall@main
- name : Install binary
run : >
cargo binstall
--no-confirm
srgn
- name : Use binary
run : srgn --version
Percakapan di atas berakhir hanya dalam total 5 detik, karena tidak diperlukan kompilasi. Untuk konteks lebih lanjut, lihat saran cargo-binstall
tentang CI.
Di Linux, gcc
berfungsi.
Di macOS, gunakan clang
.
Di Windows, MSVC berfungsi.
Pilih "Pengembangan desktop dengan C++" pada instalasi.
cargo install srgn
cargo add srgn
Lihat di sini untuk lebih lanjut.
Berbagai shell didukung untuk skrip penyelesaian shell. Misalnya, tambahkan eval "$(srgn --completions zsh)"
ke ~/.zshrc
untuk penyelesaian di ZSH. Sesi interaktif kemudian akan terlihat seperti:
Alat ini dirancang berdasarkan cakupan dan tindakan . Cakupan mempersempit bagian masukan yang akan diproses. Tindakan kemudian melakukan pemrosesan. Umumnya, cakupan dan tindakan dapat disusun, sehingga lebih dari satu cakupan dan tindakan dapat diteruskan. Keduanya bersifat opsional (tetapi tidak mengambil tindakan apa pun tidak ada gunanya); tidak menentukan cakupan berarti seluruh input berada dalam cakupan.
Pada saat yang sama, ada banyak tumpang tindih dengan tr
biasa : alat ini dirancang untuk memiliki korespondensi yang erat dalam kasus penggunaan yang paling umum, dan hanya melampauinya jika diperlukan.
Tindakan paling sederhana adalah penggantian. Ini diakses secara khusus (sebagai argumen, bukan pilihan) untuk kompatibilitas dengan tr
, dan ergonomi umum. Semua tindakan lainnya diberikan sebagai tanda, atau opsi jika tindakan tersebut mempunyai nilai.
Misalnya, penggantian satu karakter yang sederhana berfungsi seperti pada tr
:
$ echo ' Hello, World! ' | srgn ' H ' ' J '
Jello, World!
Argumen pertama adalah ruang lingkupnya (dalam kasus ini H
literal). Apa pun yang cocok dengannya akan diproses (diganti dengan J
, argumen kedua, dalam kasus ini). Namun, tidak ada konsep langsung tentang kelas karakter seperti pada tr
. Sebaliknya, secara default, cakupannya adalah pola ekspresi reguler, sehingga kelas- kelasnya dapat digunakan untuk efek serupa:
$ echo ' Hello, World! ' | srgn ' [a-z] ' ' _ '
H____, W____!
Penggantian terjadi dengan cepat di seluruh pertandingan secara default (perhatikan kelas karakter UTS, mengingatkan pada tr
's [:alnum:]
):
$ echo ' ghp_oHn0As3cr3T!! ' | srgn ' ghp_[[:alnum:]]+ ' ' * ' # A GitHub token
*!!
Fitur regex tingkat lanjut didukung, misalnya pencarian:
$ echo ' ghp_oHn0As3cr3T ' | srgn ' (?<=ghp_)[[:alnum:]]+ ' ' * '
ghp_*
Berhati-hatilah dalam menggunakan ini dengan aman, karena pola tingkat lanjut datang tanpa jaminan keamanan dan kinerja tertentu. Jika tidak digunakan, kinerja tidak akan terpengaruh.
Penggantiannya tidak terbatas pada satu karakter saja. Bisa berupa string apa saja, misalnya untuk memperbaiki kutipan ini:
$ echo ' "Using regex, I now have no issues." ' | srgn ' no issues ' ' 2 problems '
"Using regex, I now have 2 problems."
Alat ini sepenuhnya mendukung Unicode, dengan dukungan berguna untuk kelas karakter tingkat lanjut tertentu:
$ echo ' Mood: ? ' | srgn ' ? ' ' ? '
Mood: ?
$ echo ' Mood: ???? :( ' | srgn ' p{Emoji_Presentation} ' ' ? '
Mood: ???? :(
Pengganti mengetahui variabel, yang dapat diakses untuk digunakan melalui grup penangkapan regex. Grup tangkapan dapat diberi nomor, atau diberi nama secara opsional. Grup tangkapan ke nol berhubungan dengan keseluruhan pertandingan.
$ echo ' Swap It ' | srgn ' (w+) (w+) ' ' $2 $1 ' # Regular, numbered
It Swap
$ echo ' Swap It ' | srgn ' (w+) (w+) ' ' $2 $1$1$1 ' # Use as many times as you'd like
It SwapSwapSwap
$ echo ' Call +1-206-555-0100! ' | srgn ' Call (+?d-d{3}-d{3}-d{4}).+ ' ' The phone number in "$0" is: $1. ' # Variable `0` is the entire match
The phone number in "Call +1-206-555-0100!" is: +1-206-555-0100.
Kasus penggunaan yang lebih lanjut adalah, misalnya, pemfaktoran ulang kode menggunakan grup penangkap bernama (mungkin Anda dapat menemukan yang lebih berguna...):
$ echo ' let x = 3; ' | srgn ' let (?[a-z]+) = (?.+); ' ' const $var$var = $expr + $expr; '
const xx = 3 + 3;
Seperti di bash, gunakan kurung kurawal untuk membedakan variabel dari konten yang berdekatan:
$ echo ' 12 ' | srgn ' (d)(d) ' ' $2${1}1 '
211
$ echo ' 12 ' | srgn ' (d)(d) ' ' $2$11 ' # will fail (`11` is unknown)
$ echo ' 12 ' | srgn ' (d)(d) ' ' $2${11 ' # will fail (brace was not closed)
Melihat penggantinya hanya berupa string statis, kegunaannya terbatas. Di sinilah saus rahasia tr
biasanya berperan: menggunakan kelas karakternya, yang juga berlaku di posisi kedua, dengan rapi menerjemahkan dari anggota yang pertama ke yang kedua. Di sini, kelas-kelas tersebut adalah regex, dan hanya valid di posisi pertama (cakupan). Ekspresi reguler sebagai mesin negara, tidak mungkin untuk dicocokkan dengan 'daftar karakter', yang dalam tr
adalah argumen kedua (opsional). Konsep itu sudah ketinggalan zaman, dan fleksibilitasnya hilang.
Sebaliknya, tindakan yang ditawarkan, semuanya diperbaiki , digunakan. Mengintip kasus penggunaan paling umum untuk tr
mengungkapkan bahwa serangkaian tindakan yang disediakan mencakup hampir semuanya! Jangan ragu untuk mengajukan masalah jika kasus penggunaan Anda tidak tercakup.
Ke tindakan selanjutnya.
Menghapus apa pun yang ditemukan dari input. Nama bendera yang sama seperti di tr
.
$ echo ' Hello, World! ' | srgn -d ' (H|W|!) '
ello, orld
Catatan
Karena cakupan defaultnya adalah mencocokkan seluruh masukan, maka merupakan kesalahan jika menentukan penghapusan tanpa cakupan.
Memeras pengulangan karakter yang cocok dengan cakupan menjadi satu kejadian. Nama bendera yang sama seperti di tr
.
$ echo ' Helloooo Woooorld!!! ' | srgn -s ' (o|!) '
Hello World!
Jika kelas karakter dilewati, semua anggota kelas tersebut dimasukkan ke dalam anggota kelas mana pun yang pertama kali ditemui:
$ echo ' The number is: 3490834 ' | srgn -s ' d '
The number is: 3
Keserakahan dalam pencocokan tidak diubah, jadi berhati-hatilah:
$ echo ' Winter is coming... ??? ' | srgn -s ' ?+ '
Winter is coming... ???
Catatan
Polanya cocok dengan seluruh rangkaian matahari, jadi tidak ada yang perlu diperas. Musim panas terjadi.
Balikkan keserakahan jika kasus penggunaan memerlukannya:
$ echo ' Winter is coming... ??? ' | srgn -s ' ?+? ' ' ☃️ '
Winter is coming... ☃️
Catatan
Sekali lagi, seperti halnya penghapusan, menentukan pemerasan tanpa cakupan eksplisit adalah sebuah kesalahan. Jika tidak, seluruh masukan akan diperas.
Sebagian besar penggunaan tr
termasuk dalam kategori ini. Ini sangat mudah.
$ echo ' Hello, World! ' | srgn --lower
hello, world!
$ echo ' Hello, World! ' | srgn --upper
HELLO, WORLD!
$ echo ' hello, world! ' | srgn --titlecase
Hello, World!
Mengurai masukan menurut Formulir Normalisasi D, lalu membuang titik kode kategori Tandai (lihat contoh). Artinya secara kasar: mengambil karakter yang mewah, merobek bagian-bagian yang menjuntai, membuangnya.
$ echo ' Naïve jalapeño ärgert mgła ' | srgn -d ' P{ASCII} ' # Naive approach
Nave jalapeo rgert mga
$ echo ' Naïve jalapeño ärgert mgła ' | srgn --normalize # Normalize is smarter
Naive jalapeno argert mgła
Perhatikan bagaimana mgła
berada di luar cakupan NFD, karena bersifat "atom" sehingga tidak dapat terurai (setidaknya itulah yang dibisikkan ChatGPT di telinga saya).
Tindakan ini menggantikan multi-karakter, simbol ASCII dengan titik kode tunggal yang sesuai, padanan Unicode asli.
$ echo ' (A --> B) != C --- obviously ' | srgn --symbols
(A ⟶ B) ≠ C — obviously
Alternatifnya, jika Anda hanya tertarik pada matematika, manfaatkan pelingkupan:
$ echo ' A <= B --- More is--obviously--possible ' | srgn --symbols ' <= '
A ≤ B --- More is--obviously--possible
Karena terdapat korespondensi 1:1 antara simbol ASCII dan penggantinya, efeknya dapat dibalik 2 :
$ echo ' A ⇒ B ' | srgn --symbols --invert
A => B
Saat ini hanya terdapat sejumlah simbol terbatas yang didukung, namun masih banyak lagi yang dapat ditambahkan.
Tindakan ini menggantikan ejaan alternatif karakter khusus bahasa Jerman (ae, oe, ue, ss) dengan versi aslinya (ä, ö, ü, ß) 3 .
$ echo ' Gruess Gott, Neueroeffnungen, Poeten und Abenteuergruetze! ' | srgn --german
Grüß Gott, Neueröffnungen, Poeten und Abenteuergrütze!
Tindakan ini didasarkan pada daftar kata (kompilasi tanpa fitur german
jika ini membuat biner Anda terlalu membengkak). Perhatikan fitur berikut tentang contoh di atas:
Poeten
tetap apa adanya, bukannya secara naif dan keliru berpindah agama menjadi Pöten
Abenteuergrütze
tidak akan ditemukan dalam daftar kata yang masuk akal, namun tetap ditangani dengan benarAbenteuer
juga tetap apa adanya, bukannya diubah menjadi Abenteür
secara salahNeueroeffnungen
secara diam-diam membentuk elemen ue
yang tidak dimiliki oleh kata penyusunnya ( neu
, Eröffnungen
), namun masih diproses dengan benar (meskipun casingnya juga tidak cocok)Berdasarkan permintaan, penggantian mungkin dipaksakan, karena berpotensi berguna untuk nama:
$ echo ' Frau Loetter steht ueber der Mauer. ' | srgn --german-naive ' (?<=Frau )w+ '
Frau Lötter steht ueber der Mauer.
Melalui pandangan positif ke depan, hanya salam yang diberi cakupan dan oleh karena itu diubah. Mauer
dengan benar tetap apa adanya, tetapi ueber
tidak diproses. Pass kedua memperbaikinya:
$ echo ' Frau Loetter steht ueber der Mauer. ' | srgn --german-naive ' (?<=Frau )w+ ' | srgn --german
Frau Lötter steht über der Mauer.
Catatan
Opsi dan tanda yang berkaitan dengan beberapa "induk" diawali dengan nama induknya, dan akan menyiratkan induknya ketika diberikan, sehingga nama induknya tidak perlu diteruskan secara eksplisit. Itu sebabnya --german-naive
dinamai demikian, dan --german
tidak perlu diteruskan.
Perilaku ini mungkin berubah setelah clap
mendukung rangkaian subperintah.
Beberapa cabang tidak dapat memutuskan alat sederhana ini, karena alat ini beroperasi tanpa konteks bahasa. Misalnya, Busse
(bus) dan Buße
(penebusan dosa) adalah kata-kata yang sah. Secara default, penggantian dilakukan dengan rakus jika legal (bagaimanapun juga, itulah inti dari srgn
), tetapi ada tanda untuk mengubah perilaku ini:
$ echo ' Busse und Geluebte ' | srgn --german
Buße und Gelübte
$ echo ' Busse ? und Fussgaenger ?♀️ ' | srgn --german-prefer-original
Busse ? und Fußgänger ?♀️
Sebagian besar tindakan dapat disusun, kecuali jika tindakan tersebut tidak masuk akal (seperti untuk dihapus). Urutan penerapannya tetap, sehingga urutan tanda yang diberikan tidak berpengaruh (melakukan pemipaan beberapa kali merupakan alternatif, jika diperlukan). Penggantian selalu dilakukan terlebih dahulu. Secara umum, CLI dirancang untuk mencegah penyalahgunaan dan kejutan: CLI lebih memilih crash daripada melakukan sesuatu yang tidak terduga (yang tentu saja subjektif). Perhatikan bahwa banyak kombinasi yang secara teknis mungkin dilakukan, namun mungkin menghasilkan hasil yang tidak masuk akal.
Menggabungkan tindakan mungkin terlihat seperti:
$ echo ' Koeffizienten != Bruecken... ' | srgn -Sgu
KOEFFIZIENTEN ≠ BRÜCKEN...
Cakupan yang lebih sempit dapat ditentukan, dan akan berlaku untuk semua tindakan secara merata:
$ echo ' Koeffizienten != Bruecken... ' | srgn -Sgu ' bw{1,8}b '
Koeffizienten != BRÜCKEN...
Batasan kata diperlukan karena jika tidak, Koeffizienten
akan dicocokkan dengan Koeffizi
dan enten
. Perhatikan bagaimana tanda titik akhir tidak dapat diperas, misalnya. Cakupan yang diperlukan dari .
akan mengganggu yang diberikan. Perpipaan reguler memecahkan masalah ini:
$ echo ' Koeffizienten != Bruecken... ' | srgn -Sgu ' bw{1,8}b ' | srgn -s ' . '
Koeffizienten != BRÜCKEN.
Catatan: pelolosan regex ( .
) dapat dihindari menggunakan pelingkupan literal. Tindakan penggantian yang diperlakukan secara khusus juga dapat disusun:
$ echo ' Mooood: ????!!! ' | srgn -s ' p{Emoji} ' ' ? '
Mooood: ?!!!
Emoji pertama-tama diganti semuanya, lalu diperas. Perhatikan bagaimana tidak ada hal lain yang diperas.
Cakupan adalah konsep penggerak kedua setelah srgn
. Dalam kasus default, cakupan utamanya adalah ekspresi reguler. Bagian tindakan menampilkan kasus penggunaan ini secara mendetail, sehingga tidak terulang di sini. Ini diberikan sebagai argumen posisi pertama.
srgn
memperluas hal ini melalui cakupan tata bahasa yang telah dipersiapkan dan dimungkinkan melalui perpustakaan tree-sitter
yang sangat baik. Ia menawarkan fitur kueri, yang berfungsi seperti pencocokan pola terhadap struktur data pohon.
srgn
hadir dengan beberapa pertanyaan yang paling berguna. Melalui API yang dapat ditemukan (baik sebagai perpustakaan atau melalui CLI, srgn --help
), seseorang dapat mempelajari bahasa yang didukung dan kueri yang telah disiapkan dan tersedia. Setiap bahasa yang didukung dilengkapi dengan pintu keluar, memungkinkan Anda menjalankan kueri ad-hoc khusus Anda sendiri. Penetasan hadir dalam bentuk --lang-query
, di mana lang
adalah bahasa seperti python
. Lihat di bawah untuk mengetahui lebih lanjut tentang topik lanjutan ini.
Catatan
Cakupan bahasa diterapkan terlebih dahulu , jadi apa pun regex alias cakupan utama yang Anda lewati, cakupan tersebut beroperasi pada setiap konstruksi bahasa yang cocok satu per satu.
Bagian ini memperlihatkan contoh untuk beberapa kueri yang disiapkan .
unsafe
(Rust) Salah satu keuntungan dari kata kunci unsafe
di Rust adalah "grepability" -nya. Namun, rg 'unsafe'
tentu saja akan memunculkan semua string yang cocok ( rg 'bunsafeb'
membantu sampai batas tertentu), bukan hanya yang ada dalam kata kunci bahasa Rust yang sebenarnya. srgn
membantu menjadikannya lebih tepat. Misalnya:
// Oh no, an unsafe module!
mod scary_unsafe_operations {
pub unsafe fn unsafe_array_access ( arr : & [ i32 ] , index : usize ) -> i32 {
// UNSAFE: This function performs unsafe array access without bounds checking
* arr . get_unchecked ( index )
}
pub fn call_unsafe_function ( ) {
let unsafe_numbers = vec ! [ 1 , 2 , 3 , 4 , 5 ] ;
println ! ( "About to perform an unsafe operation!" ) ;
let result = unsafe {
// Calling an unsafe function
unsafe_array_access ( & unsafe_numbers , 10 )
} ;
println ! ( "Result of unsafe operation: {}" , result ) ;
}
}
dapat dicari sebagai