Ein grep
-ähnliches Tool, das die Quellcodesyntax versteht und neben der Suche auch Manipulationen ermöglicht.
Reguläre Ausdrücke sind wie grep
ein Kernelement. Im Gegensatz zu grep
ermöglichen zusätzliche Funktionen eine höhere Präzision mit Optionen zur Manipulation . Dies ermöglicht es srgn
, entlang der Dimensionen regulärer Ausdrücke zu arbeiten, und IDE-Tools ( Alle umbenennen , alle Referenzen finden , ...) allein können dies nicht, indem sie diese ergänzen.
srgn
ist um zu ergreifende Aktionen (sofern vorhanden) organisiert und agiert nur innerhalb präziser, optional sprachgrammatikbewusster Bereiche . Stellen Sie sich die vorhandenen Tools als eine Mischung aus tr
, sed
, ripgrep und tree-sitter
vor, mit dem Designziel der Einfachheit : Wenn Sie Regex und die Grundlagen der Sprache kennen, mit der Sie arbeiten, können Sie loslegen .
Tipp
Alle hier angezeigten Codeausschnitte werden im Rahmen von Unit-Tests mit der tatsächlichen srgn
Binärdatei überprüft. Was hier gezeigt wird, funktioniert garantiert.
Die einfachste Verwendung srgn
funktioniert ähnlich wie tr
:
$ echo ' Hello World! ' | srgn ' [wW]orld ' ' there ' # replacement
Hello there !
Übereinstimmungen für das reguläre Ausdrucksmuster '[wW]orld'
(der Bereich ) werden (die Aktion ) durch das zweite Positionsargument ersetzt. Es können null oder mehr Aktionen angegeben werden:
$ 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 !
Der Austausch wird immer zuerst durchgeführt und positionell angegeben. Alle anderen Aktionen werden danach angewendet und als Befehlszeilenflags angegeben.
Ebenso kann mehr als ein Bereich angegeben werden: Zusätzlich zum Regex-Muster kann ein grammatikaler Sprachbereich angegeben werden, der sich auf syntaktische Elemente des Quellcodes bezieht (denken Sie beispielsweise an „alle Körper von class
in Python“). ). Wenn beides angegeben ist, wird das reguläre Ausdrucksmuster nur innerhalb dieses ersten Sprachbereichs angewendet . Dies ermöglicht eine Suche und Manipulation mit einer Genauigkeit, die normalerweise mit einfachen regulären Ausdrücken nicht möglich wäre, und ermöglicht die Bereitstellung einer anderen Dimension als Tools wie „Alle umbenennen“ in IDEs.
Betrachten Sie zum Beispiel diese (sinnlose) Python-Quelldatei:
"""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 )
die durchsucht werden kann mit:
$ cat birds.py | srgn --python ' class ' ' age '
11: age: int
15: self.age += 1
Die Zeichenfolge age
wurde nur innerhalb von Python- class
gesucht und gefunden (und nicht beispielsweise in Funktionskörpern wie register_bird
, wo age
ebenfalls vorkommt und in Vanilla grep
nahezu unmöglich von der Berücksichtigung auszuschließen wäre). Standardmäßig werden in diesem „Suchmodus“ auch Zeilennummern gedruckt. Der Suchmodus wird aufgerufen, wenn keine Aktionen angegeben sind und eine Sprache wie --python
den Wert 1 erhält – stellen Sie sich das wie „ripgrep, aber mit syntaktischen Sprachelementen“ vor.
Die Suche kann auch zeilenübergreifend durchgeführt werden, um beispielsweise Methoden (auch bekannt als def
innerhalb class
) zu finden, denen Dokumentzeichenfolgen fehlen:
$ cat birds.py | srgn --python ' class ' ' def .+:ns+[^"s]{3} ' # do not try this pattern at home
13: def celebrate_birthday(self):
14: print("?")
Beachten Sie, dass dies weder from_egg
(hat einen Dokumentstring) noch register_bird
(keine Methode, def
außerhalb von class
) auftaucht.
Auch Sprachbereiche selbst können mehrfach angegeben werden. Zum Beispiel im Rust-Snippet
pub enum Genre {
Rock ( Subgenre ) ,
Jazz ,
}
const MOST_POPULAR_SUBGENRE : Subgenre = Subgenre :: Something ;
pub struct Musician {
name : String ,
genres : Vec < Subgenre > ,
}
Mehrere Elemente können chirurgisch aufgeschlüsselt werden
$ cat music.rs | srgn --rust ' pub-enum ' --rust ' type-identifier ' ' Subgenre ' # AND'ed together
2: Rock(Subgenre),
wobei nur Zeilen zurückgegeben werden, die alle Kriterien erfüllen, und sich wie ein logisches und zwischen allen Bedingungen verhalten. Beachten Sie, dass Bedingungen von links nach rechts ausgewertet werden, sodass einige Kombinationen keinen Sinn ergeben: Beispielsweise gibt die Suche nach einem Python class
innerhalb von Python doc-strings
normalerweise nichts zurück. Die Umkehrung funktioniert jedoch wie erwartet:
$ cat birds.py | srgn --py ' class ' --py ' doc-strings '
8: """A bird!"""
19: """Create a bird from an egg."""
Es werden keine Dokumentzeichenfolgen außerhalb class
angezeigt!
Das Flag -j
ändert dieses Verhalten: von der Überschneidung von links nach rechts bis zur unabhängigen Ausführung aller Abfragen und der Verknüpfung ihrer Ergebnisse, sodass Sie auf mehrere Arten gleichzeitig suchen können:
$ 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!
Das Muster bird[^s]
wurde ebenfalls innerhalb von Kommentaren oder Dokumentzeichenfolgen gefunden, nicht nur „Dokumentzeichenfolgen innerhalb von Kommentaren“.
Wenn keine Standardeingabe erfolgt, weiß srgn
, wie relevante Quelldateien automatisch gefunden werden, beispielsweise in diesem Repository:
$ 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
Es durchsucht rekursiv sein aktuelles Verzeichnis, findet Dateien basierend auf Dateierweiterungen und Shebang-Zeilen und verarbeitet es mit sehr hoher Geschwindigkeit. Beispielsweise findet und druckt srgn --go strings 'd+'
alle ca. 140.000 Ziffernfolgen in literalen Go-Strings innerhalb der Kubernetes-Codebasis von ca. 3.000.000 Zeilen Go-Code innerhalb von 3 Sekunden auf 12 Kernen von M3. Weitere Informationen zum Arbeiten mit vielen Dateien finden Sie weiter unten.
Bereiche und Aktionen können nahezu beliebig kombiniert werden (obwohl viele Kombinationen weder sinnvoll noch sinnvoll sind). Betrachten Sie beispielsweise dieses Python-Snippet (Beispiele für die Verwendung anderer unterstützter Sprachen finden Sie unten):
"""GNU module."""
def GNU_says_moo ():
"""The GNU function -> say moo -> ✅"""
GNU = """
GNU
""" # the GNU...
print ( GNU + " says moo" ) # ...says moo
gegen die der folgende Befehl ausgeführt wird:
cat gnu.py | srgn --titlecase --python ' doc-strings ' ' (?' ' $1: GNU ? is not Unix '
Die Anatomie dieser Anrufung ist:
--titlecase
(eine Aktion) schreibt alles, was im Geltungsbereich gefunden wird, in Großbuchstaben um
--python 'doc-strings'
(ein Bereich) gilt gemäß der Python-Sprachgrammatik für Docstrings (d. h. berücksichtigt nur diese).
'(? (ein Bereich) sieht nur den Bereich, der bereits durch die vorherige Option festgelegt wurde, und grenzt ihn weiter ein. Es kann niemals den bisherigen Umfang erweitern. Der Bereich des regulären Ausdrucks wird nach allen Sprachbereichen angewendet.
(? ist eine negative Lookbehind-Syntax und zeigt, wie diese erweiterte Funktion verfügbar ist. Zeichenfolgen von
GNU
mit dem Präfix The
werden nicht berücksichtigt.
'$1: GNU ? is not Unix'
(eine Aktion) ersetzt jedes übereinstimmende Vorkommen (dh jeden Eingabeabschnitt, der sich im Gültigkeitsbereich befindet) durch diese Zeichenfolge. Übereinstimmende Vorkommen sind Muster von '(? nur innerhalb von Python-Dokumentzeichenfolgen. Insbesondere zeigt diese Ersatzzeichenfolge:
$1
, das den von der ersten erfassenden Regex-Gruppe erfassten Inhalt enthält. Das ist ([az]+)
, da (? nicht erfasst wird.
Der Befehl nutzt mehrere Bereiche (Sprache und Regex-Muster) und mehrere Aktionen (Ersetzung und Groß-/Kleinschreibung von Titeln). Das Ergebnis lautet dann
"""Module: GNU ? Is Not Unix."""
def GNU_says_moo ():
"""The GNU function -> say moo -> ✅"""
GNU = """
GNU
""" # the GNU...
print ( GNU + " says moo" ) # ...says moo
wobei sich die Änderungen auf Folgendes beschränken:
- """GNU module."""
+ """Module: GNU ? Is Not Unix."""
def GNU_says_moo():
"""The GNU -> say moo -> ✅"""
Warnung
Während sich srgn
in der Beta-Phase (Hauptversion 0) befindet, stellen Sie sicher, dass Sie nur Dateien (rekursiv) verarbeiten, die Sie sicher wiederherstellen können.
Der Suchmodus überschreibt keine Dateien und ist daher immer sicher.
Unten finden Sie die vollständige Hilfeausgabe des Tools.
Notiz
Unterstützte Sprachen sind
Laden Sie eine vorgefertigte Binärdatei aus den Versionen herunter.
Diese Kiste stellt ihre Binärdateien in einem Format bereit, das mit cargo-binstall
kompatibel ist:
cargo install cargo-binstall
“ aus (kann eine Weile dauern)cargo binstall srgn
aus (einige Sekunden, da vorgefertigte Binärdateien von GitHub heruntergeladen werden).Diese Schritte funktionieren garantiert™, da sie in CI getestet werden. Sie funktionieren auch, wenn für Ihre Plattform keine vorgefertigten Binärdateien verfügbar sind, da das Tool auf die Kompilierung aus dem Quellcode zurückgreift.
Eine Formel ist verfügbar über:
brew install srgn
Verfügbar über Unstable:
nix-shell -p srgn
Erhältlich über die AUR.
Ein Port ist verfügbar:
sudo port install srgn
Bei allen GitHub Actions-Runner-Images ist cargo
vorinstalliert, und cargo-binstall
bietet eine praktische GitHub-Aktion:
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
Das Obige ist in insgesamt nur 5 Sekunden abgeschlossen, da keine Kompilierung erforderlich ist. Weiteren Kontext finden Sie in den Ratschlägen von cargo-binstall
“ zu CI.
Unter Linux funktioniert gcc
.
Verwenden Sie unter macOS clang
.
Unter Windows funktioniert MSVC.
Wählen Sie bei der Installation „Desktop-Entwicklung mit C++“ aus.
cargo install srgn
aus cargo add srgn
Weitere Informationen finden Sie hier.
Für Shell-Vervollständigungsskripte werden verschiedene Shells unterstützt. Hängen Sie beispielsweise eval "$(srgn --completions zsh)"
an ~/.zshrc
für Vervollständigungen in ZSH an. Eine interaktive Sitzung kann dann wie folgt aussehen:
Das Tool ist auf Bereiche und Aktionen ausgelegt. Bereiche grenzen die zu verarbeitenden Teile der Eingabe ein. Aktionen führen dann die Verarbeitung durch. Im Allgemeinen sind sowohl Bereiche als auch Aktionen zusammensetzbar, sodass von jedem mehr als einer übergeben werden kann. Beides ist optional (es ist jedoch sinnlos, keine Maßnahmen zu ergreifen). Wenn Sie keinen Bereich angeben, bedeutet dies, dass sich die gesamte Eingabe im Bereich befindet.
Gleichzeitig gibt es erhebliche Überschneidungen mit einfachem tr
: Das Tool ist so konzipiert, dass es in den häufigsten Anwendungsfällen eine enge Übereinstimmung aufweist und nur bei Bedarf darüber hinausgeht.
Die einfachste Maßnahme ist der Austausch. Aus Gründen der Kompatibilität mit tr
und allgemeiner Ergonomie wird speziell darauf zugegriffen (als Argument, nicht als Option). Alle anderen Aktionen werden als Flags oder Optionen angegeben, sofern sie einen Wert annehmen.
Einfache Einzelzeichenersetzungen funktionieren beispielsweise wie in tr
:
$ echo ' Hello, World! ' | srgn ' H ' ' J '
Jello, World!
Das erste Argument ist der Gültigkeitsbereich (in diesem Fall das Literal H
). Alles, was damit übereinstimmt, unterliegt der Verarbeitung (Ersetzung durch J
, in diesem Fall das zweite Argument). Allerdings gibt es kein direktes Konzept von Zeichenklassen wie in tr
. Stattdessen ist der Bereich standardmäßig ein reguläres Ausdrucksmuster, sodass seine Klassen mit ähnlichem Effekt verwendet werden können:
$ echo ' Hello, World! ' | srgn ' [a-z] ' ' _ '
H____, W____!
Die Ersetzung erfolgt standardmäßig gierig über die gesamte Übereinstimmung hinweg (beachten Sie die UTS-Zeichenklasse, die an tr
erinnert [:alnum:]
):
$ echo ' ghp_oHn0As3cr3T!! ' | srgn ' ghp_[[:alnum:]]+ ' ' * ' # A GitHub token
*!!
Erweiterte Regex-Funktionen werden unterstützt, zum Beispiel Lookarounds:
$ echo ' ghp_oHn0As3cr3T ' | srgn ' (?<=ghp_)[[:alnum:]]+ ' ' * '
ghp_*
Seien Sie vorsichtig bei der sicheren Verwendung dieser Muster, da für fortgeschrittene Muster keine bestimmten Sicherheits- und Leistungsgarantien gelten. Wenn sie nicht verwendet werden, wird die Leistung nicht beeinträchtigt.
Die Ersetzung ist nicht auf ein einzelnes Zeichen beschränkt. Es kann eine beliebige Zeichenfolge sein, um beispielsweise dieses Zitat zu korrigieren:
$ echo ' "Using regex, I now have no issues." ' | srgn ' no issues ' ' 2 problems '
"Using regex, I now have 2 problems."
Das Tool ist vollständig Unicode-fähig und bietet nützliche Unterstützung für bestimmte erweiterte Zeichenklassen:
$ echo ' Mood: ? ' | srgn ' ? ' ' ? '
Mood: ?
$ echo ' Mood: ???? :( ' | srgn ' p{Emoji_Presentation} ' ' ? '
Mood: ???? :(
Ersetzungen kennen Variablen, die über Regex-Erfassungsgruppen zur Verwendung zugänglich gemacht werden. Erfassungsgruppen können nummeriert oder optional benannt werden. Die nullte Erfassungsgruppe entspricht der gesamten Übereinstimmung.
$ 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.
Ein fortgeschrittenerer Anwendungsfall ist beispielsweise das Code-Refactoring mithilfe benannter Capture-Gruppen (vielleicht fällt Ihnen eine nützlichere ein ...):
$ echo ' let x = 3; ' | srgn ' let (?[a-z]+) = (?.+); ' ' const $var$var = $expr + $expr; '
const xx = 3 + 3;
Verwenden Sie wie in Bash geschweifte Klammern, um Variablen von unmittelbar angrenzendem Inhalt zu unterscheiden:
$ 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)
Da es sich bei der Ersetzung lediglich um eine statische Zeichenfolge handelt, ist ihr Nutzen begrenzt. Hier kommt normalerweise die geheime Soße von tr
ins Spiel: die Verwendung seiner Zeichenklassen, die auch an der zweiten Position gültig sind, und eine saubere Übersetzung von Mitgliedern der ersten in die zweite. Hier sind diese Klassen stattdessen reguläre Ausdrücke und nur an der ersten Position (dem Gültigkeitsbereich) gültig. Da es sich bei einem regulären Ausdruck um eine Zustandsmaschine handelt, ist es unmöglich, ihn einer „Liste von Zeichen“ zuzuordnen, die in tr
das zweite (optionale) Argument ist. Dieses Konzept ist überholt und seine Flexibilität ist verloren gegangen.
Stattdessen werden die angebotenen, allesamt festen Aktionen genutzt. Ein Blick auf die häufigsten Anwendungsfälle für tr
zeigt, dass die bereitgestellten Aktionen praktisch alle davon abdecken! Melden Sie gerne ein Problem, wenn Ihr Anwendungsfall nicht abgedeckt ist.
Auf zur nächsten Aktion.
Entfernt alles, was aus der Eingabe gefunden wird. Gleicher Flagname wie in tr
.
$ echo ' Hello, World! ' | srgn -d ' (H|W|!) '
ello, orld
Notiz
Da der Standardbereich die gesamte Eingabe abgleichen soll, ist es ein Fehler, das Löschen ohne einen Bereich anzugeben.
Komprimiert Wiederholungen von Zeichen, die dem Bereich entsprechen, in einzelne Vorkommen. Gleicher Flagname wie in tr
.
$ echo ' Helloooo Woooorld!!! ' | srgn -s ' (o|!) '
Hello World!
Wenn eine Zeichenklasse übergeben wird, werden alle Mitglieder dieser Klasse in das zuerst angetroffene Klassenmitglied gequetscht:
$ echo ' The number is: 3490834 ' | srgn -s ' d '
The number is: 3
Die Gier beim Matching wird nicht verändert, also achten Sie darauf:
$ echo ' Winter is coming... ??? ' | srgn -s ' ?+ '
Winter is coming... ???
Notiz
Das Muster stimmte mit der gesamten Sonnenreihe überein, es gibt also nichts zu quetschen. Der Sommer herrscht.
Gier umkehren, wenn der Anwendungsfall dies erfordert:
$ echo ' Winter is coming... ??? ' | srgn -s ' ?+? ' ' ☃️ '
Winter is coming... ☃️
Notiz
Auch hier ist es wie beim Löschen ein Fehler, das Komprimieren ohne expliziten Bereich anzugeben. Andernfalls wird die gesamte Eingabe gestaucht.
Ein großer Teil der tr
Nutzung fällt in diese Kategorie. Es ist sehr einfach.
$ echo ' Hello, World! ' | srgn --lower
hello, world!
$ echo ' Hello, World! ' | srgn --upper
HELLO, WORLD!
$ echo ' hello, world! ' | srgn --titlecase
Hello, World!
Zerlegt die Eingabe gemäß Normalisierungsform D und verwirft dann Codepunkte der Kategorie „Markieren“ (siehe Beispiele). Das bedeutet in etwa: Schicke Figur nehmen, baumelnde Teile abreißen, wegwerfen.
$ 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
Beachten Sie, dass mgła
außerhalb des Geltungsbereichs von NFD liegt, da es „atomar“ und daher nicht zerlegbar ist (zumindest flüstert mir ChatGPT das ins Ohr).
Diese Aktion ersetzt ASCII-Symbole mit mehreren Zeichen durch entsprechende native Unicode-Gegenstücke mit einem Codepunkt.
$ echo ' (A --> B) != C --- obviously ' | srgn --symbols
(A ⟶ B) ≠ C — obviously
Wenn Sie sich nur für Mathematik interessieren, nutzen Sie alternativ die Scoping-Methode:
$ echo ' A <= B --- More is--obviously--possible ' | srgn --symbols ' <= '
A ≤ B --- More is--obviously--possible
Da zwischen einem ASCII-Symbol und seinem Ersatz eine 1:1-Entsprechung besteht, ist der Effekt reversibel 2 :
$ echo ' A ⇒ B ' | srgn --symbols --invert
A => B
Derzeit wird nur eine begrenzte Anzahl von Symbolen unterstützt, es können jedoch weitere hinzugefügt werden.
Diese Aktion ersetzt alternative Schreibweisen deutscher Sonderzeichen (ae, oe, ue, ss) durch ihre nativen Versionen (ä, ö, ü, ß) 3 .
$ echo ' Gruess Gott, Neueroeffnungen, Poeten und Abenteuergruetze! ' | srgn --german
Grüß Gott, Neueröffnungen, Poeten und Abenteuergrütze!
Diese Aktion basiert auf einer Wortliste (kompilieren Sie ohne german
Funktion, wenn dies Ihre Binärdatei zu sehr aufbläht). Beachten Sie die folgenden Merkmale des obigen Beispiels:
Poeten
blieb so, wie er war, anstatt sich naiv und fälschlicherweise zu Pöten
zu bekehrenAbenteuergrütze
zwar in keiner vernünftigen Wortliste auftauchen, wurde aber dennoch ordentlich behandeltAbenteuer
war zwar Teil eines zusammengesetzten Wortes, blieb aber ebenfalls so, wie es ist, anstatt fälschlicherweise in Abenteür
umgewandelt zu werdenNeueroeffnungen
heimlich ein ue
Element, das keines der konstituierenden Wörter ( neu
, Eröffnungen
) besitzt, wird aber dennoch korrekt verarbeitet (auch trotz der nicht übereinstimmenden Schreibweise).Auf Wunsch können Ersetzungen erzwungen werden, was bei Namen ggf. sinnvoll ist:
$ echo ' Frau Loetter steht ueber der Mauer. ' | srgn --german-naive ' (?<=Frau )w+ '
Frau Lötter steht ueber der Mauer.
Durch positive Vorausschau wurde lediglich die Anrede eingeschränkt und somit geändert. Mauer
blieb korrekterweise so, wie sie ist, aber ueber
wurde nicht bearbeitet. Ein zweiter Durchgang behebt dieses Problem:
$ echo ' Frau Loetter steht ueber der Mauer. ' | srgn --german-naive ' (?<=Frau )w+ ' | srgn --german
Frau Lötter steht über der Mauer.
Notiz
Optionen und Flags, die sich auf einige „übergeordnete Elemente“ beziehen, werden mit dem Namen ihres übergeordneten Elements vorangestellt und implizieren bei Angabe ihr übergeordnetes Element, sodass letzteres nicht explizit übergeben werden muss. Deshalb wird --german-naive
so benannt, wie es ist, und --german
muss nicht übergeben werden.
Dieses Verhalten kann sich ändern, sobald clap
die Verkettung von Unterbefehlen unterstützt.
Einige Zweige sind für dieses bescheidene Tool nicht entscheidbar, da es ohne Sprachkontext arbeitet. Beispielsweise sind sowohl Busse
(Busse) als auch Buße
(Buße) juristische Wörter. Standardmäßig werden Ersetzungen gierig durchgeführt, wenn sie zulässig sind (das ist schließlich der Sinn von srgn
), aber es gibt ein Flag zum Umschalten dieses Verhaltens:
$ echo ' Busse und Geluebte ' | srgn --german
Buße und Gelübte
$ echo ' Busse ? und Fussgaenger ?♀️ ' | srgn --german-prefer-original
Busse ? und Fußgänger ?♀️
Die meisten Aktionen sind zusammensetzbar, es sei denn, dies wäre unsinnig (z. B. beim Löschen). Ihre Anwendungsreihenfolge ist festgelegt, sodass die Reihenfolge der angegebenen Flags keinen Einfluss hat (bei Bedarf ist die Verrohrung mehrerer Läufe eine Alternative). Ersetzungen erfolgen immer zuerst. Im Allgemeinen ist die CLI darauf ausgelegt, Missbrauch und Überraschungen zu verhindern: Sie stürzt lieber ab als etwas Unerwartetes zu tun (was natürlich subjektiv ist). Beachten Sie, dass viele Kombinationen technisch möglich sind , aber zu unsinnigen Ergebnissen führen können.
Das Kombinieren von Aktionen könnte wie folgt aussehen:
$ echo ' Koeffizienten != Bruecken... ' | srgn -Sgu
KOEFFIZIENTEN ≠ BRÜCKEN...
Es kann ein engerer Geltungsbereich festgelegt werden, der für alle Aktionen gleichermaßen gilt:
$ echo ' Koeffizienten != Bruecken... ' | srgn -Sgu ' bw{1,8}b '
Koeffizienten != BRÜCKEN...
Die Wortgrenzen sind erforderlich, da sonst Koeffizienten
als Koeffizi
und enten
abgeglichen wird. Beachten Sie, dass die nachfolgenden Punkte beispielsweise nicht gestaucht werden können. Der erforderliche Bereich von .
würde das Gegebene stören. Regelmäßige Rohrleitungen lösen dieses Problem:
$ echo ' Koeffizienten != Bruecken... ' | srgn -Sgu ' bw{1,8}b ' | srgn -s ' . '
Koeffizienten != BRÜCKEN.
Hinweis: Regex-Escapezeichen ( .
) können durch literales Scoping umgangen werden. Auch die speziell behandelte Ersatzhandlung ist zusammensetzbar:
$ echo ' Mooood: ????!!! ' | srgn -s ' p{Emoji} ' ' ? '
Mooood: ?!!!
Emojis werden zunächst alle ausgetauscht und dann gequetscht. Beachten Sie, dass nichts anderes gedrückt wird.
Scopes sind das zweite Antriebskonzept von srgn
. Im Standardfall ist der Hauptbereich ein regulärer Ausdruck. Im Abschnitt „Aktionen“ wurde dieser Anwendungsfall ausführlicher dargestellt, sodass er hier nicht wiederholt wird. Es wird als erstes Positionsargument angegeben.
srgn
erweitert dies durch vorbereitete, sprachgrammatische Bereiche, die durch die hervorragende tree-sitter
-Bibliothek ermöglicht werden. Es bietet eine Abfragefunktion, die ähnlich wie ein Mustervergleich mit einer Baumdatenstruktur funktioniert.
Im Lieferumfang von srgn
sind einige der nützlichsten dieser Abfragen enthalten. Über die auffindbare API (entweder als Bibliothek oder über CLI, srgn --help
) kann man sich über die unterstützten Sprachen und die verfügbaren, vorbereiteten Abfragen informieren. Jede unterstützte Sprache verfügt über eine Notluke, die es Ihnen ermöglicht, Ihre eigenen, benutzerdefinierten Ad-hoc-Abfragen auszuführen. Die Schraffur hat die Form --lang-query
, wobei lang
eine Sprache wie python
ist. Weitere Informationen zu diesem fortgeschrittenen Thema finden Sie weiter unten.
Notiz
Sprachbereiche werden zuerst angewendet. Unabhängig davon, welchen Regex bzw. Hauptbereich Sie übergeben, wird er auf jedes übereinstimmende Sprachkonstrukt einzeln angewendet.
Dieser Abschnitt zeigt Beispiele für einige der vorbereiteten Abfragen .
unsafe
Codes finden (Rust) Ein Vorteil des unsafe
Schlüsselworts in Rust ist seine „Grepability“. Allerdings wird ein rg 'unsafe'
natürlich alle String-Übereinstimmungen aufdecken ( rg 'bunsafeb'
hilft bis zu einem gewissen Grad), nicht nur die im eigentlichen Rust-Sprachschlüsselwort. srgn
hilft, dies genauer zu machen. Zum Beispiel:
// 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 ) ;
}
}
kann gesucht werden als