Una herramienta similar a grep
que comprende la sintaxis del código fuente y permite la manipulación además de la búsqueda.
Al igual que grep
, las expresiones regulares son una primitiva central. A diferencia de grep
, las capacidades adicionales permiten una mayor precisión , con opciones de manipulación . Esto permite que srgn
opere a lo largo de dimensiones de expresiones regulares y las herramientas IDE ( Renombrar todo , Buscar todas las referencias , ...) por sí solas no pueden, complementándolas.
srgn
está organizado en torno a acciones a tomar (si corresponde), actuando solo dentro de alcances precisos y opcionalmente conscientes de la gramática del lenguaje . En términos de herramientas existentes, considérelo como una combinación de tr
, sed
, ripgrep y tree-sitter
, con un objetivo de diseño de simplicidad : si conoce las expresiones regulares y los conceptos básicos del lenguaje con el que está trabajando, está listo para comenzar. .
Consejo
Todos los fragmentos de código que se muestran aquí se verifican como parte de pruebas unitarias utilizando el binario srgn
real. Se garantiza que lo que se muestra aquí funcionará.
El uso más simple srgn
funciona de manera similar a tr
:
$ echo ' Hello World! ' | srgn ' [wW]orld ' ' there ' # replacement
Hello there !
Las coincidencias para el patrón de expresión regular '[wW]orld'
(el alcance ) se reemplazan (la acción ) por el segundo argumento posicional. Se pueden especificar cero o más acciones:
$ 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 !
El reemplazo siempre se realiza primero y se especifica posicionalmente. Cualquier otra acción se aplica después y se proporciona como indicadores de línea de comando.
De manera similar, se puede especificar más de un alcance: además del patrón de expresiones regulares, se puede proporcionar un alcance que tenga en cuenta la gramática del lenguaje , que abarca elementos sintácticos del código fuente (piense, por ejemplo, en "todos los cuerpos de definiciones class
en Python"). ). Si se proporcionan ambos, el patrón de expresión regular solo se aplica dentro del primer alcance del lenguaje . Esto permite la búsqueda y manipulación con una precisión que normalmente no es posible utilizando expresiones regulares simples y brinda una dimensión diferente a herramientas como Cambiar nombre de todo en los IDE.
Por ejemplo, considere este archivo fuente de Python (inútil):
"""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 )
que se puede buscar usando:
$ cat birds.py | srgn --python ' class ' ' age '
11: age: int
15: self.age += 1
La cadena age
se buscó y encontró solo dentro de las definiciones class
de Python (y no, por ejemplo, en cuerpos de funciones como register_bird
, donde age
también ocurre y sería casi imposible excluirla de la consideración en vanilla grep
). De forma predeterminada, este 'modo de búsqueda' también imprime números de línea. Se ingresa al modo de búsqueda si no se especifica ninguna acción y se le asigna 1 a un lenguaje como --python
; considérelo como 'ripgrep pero con elementos de lenguaje sintáctico'.
La búsqueda también se puede realizar entre líneas, por ejemplo para encontrar métodos (también conocidos como def
dentro de class
) que carecen de cadenas de documentación:
$ cat birds.py | srgn --python ' class ' ' def .+:ns+[^"s]{3} ' # do not try this pattern at home
13: def celebrate_birthday(self):
14: print("?")
Tenga en cuenta que esto no aparece ni from_egg
(tiene una cadena de documentación) ni register_bird
(no es un método, def
fuera de class
).
Los propios ámbitos del idioma también se pueden especificar varias veces. Por ejemplo, en el fragmento de Rust
pub enum Genre {
Rock ( Subgenre ) ,
Jazz ,
}
const MOST_POPULAR_SUBGENRE : Subgenre = Subgenre :: Something ;
pub struct Musician {
name : String ,
genres : Vec < Subgenre > ,
}
Se pueden perforar quirúrgicamente varios elementos como sea posible.
$ cat music.rs | srgn --rust ' pub-enum ' --rust ' type-identifier ' ' Subgenre ' # AND'ed together
2: Rock(Subgenre),
donde solo se devuelven líneas que coinciden con todos los criterios, actuando como una lógica y entre todas las condiciones. Tenga en cuenta que las condiciones se evalúan de izquierda a derecha, lo que impide que algunas combinaciones tengan sentido: por ejemplo, la búsqueda de un cuerpo class
de Python dentro de doc-strings
de Python generalmente no devuelve nada. Sin embargo, lo inverso funciona como se esperaba:
$ cat birds.py | srgn --py ' class ' --py ' doc-strings '
8: """A bird!"""
19: """Create a bird from an egg."""
¡No aparecen cadenas de documentación fuera de los cuerpos class
!
La bandera -j
cambia este comportamiento: de cruzar de izquierda a derecha a ejecutar todas las consultas de forma independiente y unir sus resultados, lo que le permite buscar de varias formas a la vez:
$ 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!
El patrón bird[^s]
también se encontró dentro de los comentarios o cadenas de documentos, no solo "cadenas de documentos dentro de los comentarios".
Si no se proporciona una entrada estándar, srgn
sabe cómo encontrar archivos fuente relevantes automáticamente, por ejemplo en este repositorio:
$ 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
Recorre recursivamente su directorio actual, encuentra archivos basados en extensiones de archivo y líneas shebang, y los procesa a muy alta velocidad. Por ejemplo, srgn --go strings 'd+'
busca e imprime las ~140.000 ejecuciones de dígitos en cadenas Go literales dentro del código base de Kubernetes de ~3.000.000 de líneas de código Go en 3 segundos en 12 núcleos de M3. Para obtener más información sobre cómo trabajar con muchos archivos, consulte a continuación.
Los alcances y las acciones se pueden combinar casi arbitrariamente (aunque muchas combinaciones no serán útiles, ni siquiera significativas). Por ejemplo, considere este fragmento de Python (para ver ejemplos que utilizan otros lenguajes compatibles, consulte a continuación):
"""GNU module."""
def GNU_says_moo ():
"""The GNU function -> say moo -> ✅"""
GNU = """
GNU
""" # the GNU...
print ( GNU + " says moo" ) # ...says moo
contra el cual se ejecuta el siguiente comando:
cat gnu.py | srgn --titlecase --python ' doc-strings ' ' (?' ' $1: GNU ? is not Unix '
La anatomía de esa invocación es:
--titlecase
(una acción) pondrá título a todo lo que se encuentre en el alcance
--python 'doc-strings'
(un alcance) abarcará (es decir, solo tomará en consideración) cadenas de documentos de acuerdo con la gramática del lenguaje Python
'(? (un alcance) ve solo lo que ya estaba dentro del alcance de la opción anterior y lo reducirá aún más. Nunca podrá ampliar el alcance anterior. El alcance de la expresión regular se aplica después de cualquier alcance del idioma.
(? es una sintaxis inversa negativa, lo que demuestra cómo está disponible esta característica avanzada. No se considerarán cadenas de
GNU
con el prefijo The
.
'$1: GNU ? is not Unix'
(una acción) reemplazará cada aparición coincidente (es decir, cada sección de entrada que se encuentre dentro del alcance) con esta cadena. Las ocurrencias coincidentes son patrones de '(? solo dentro de las cadenas de documentación de Python. En particular, esta cadena de reemplazo demuestra:
$1
, que transporta el contenido capturado por el primer grupo de expresiones regulares de captura. Eso es ([az]+)
, ya que (? no está capturando.
El comando utiliza múltiples ámbitos (idioma y patrón de expresiones regulares) y múltiples acciones (reemplazo y colocación de títulos). El resultado luego dice
"""Module: GNU ? Is Not Unix."""
def GNU_says_moo ():
"""The GNU function -> say moo -> ✅"""
GNU = """
GNU
""" # the GNU...
print ( GNU + " says moo" ) # ...says moo
donde los cambios se limitan a:
- """GNU module."""
+ """Module: GNU ? Is Not Unix."""
def GNU_says_moo():
"""The GNU -> say moo -> ✅"""
Advertencia
Mientras srgn
esté en versión beta (versión principal 0), asegúrese de procesar solo (recursivamente) archivos que pueda restaurar de forma segura.
El modo de búsqueda no sobrescribe archivos, por lo que siempre es seguro.
Consulte a continuación el resultado de ayuda completo de la herramienta.
Nota
Los idiomas admitidos son
Descargue un binario prediseñado de las versiones.
Esta caja proporciona sus binarios en un formato compatible con cargo-binstall
:
cargo install cargo-binstall
(puede tardar un poco)cargo binstall srgn
(un par de segundos, mientras descarga archivos binarios prediseñados desde GitHub)Se garantiza que estos pasos funcionarán™, ya que están probados en CI. También funcionan si no hay archivos binarios prediseñados disponibles para su plataforma, ya que la herramienta volverá a compilar desde la fuente.
Una fórmula está disponible a través de:
brew install srgn
Disponible vía inestable:
nix-shell -p srgn
Disponible a través de la AUR.
Hay un puerto disponible:
sudo port install srgn
Todas las imágenes del ejecutor de GitHub Actions vienen con cargo
preinstalado y cargo-binstall
proporciona una GitHub Action conveniente:
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
Lo anterior concluye en sólo 5 segundos en total, ya que no se requiere compilación. Para obtener más contexto, consulte el consejo de cargo-binstall
sobre CI.
En Linux, gcc
funciona.
En macOS, utilice clang
.
En Windows, MSVC funciona.
Seleccione "Desarrollo de escritorio con C++" durante la instalación.
cargo install srgn
cargo add srgn
Consulte aquí para obtener más información.
Se admiten varios shells para los scripts de finalización de shell. Por ejemplo, agregue eval "$(srgn --completions zsh)"
a ~/.zshrc
para completar en ZSH. Entonces, una sesión interactiva puede verse así:
La herramienta está diseñada en torno a alcances y acciones . Los alcances limitan las partes de la entrada a procesar. Luego, las acciones realizan el procesamiento. Generalmente, tanto los alcances como las acciones son componibles, por lo que se puede pasar más de uno de cada uno. Ambos son opcionales (pero no tiene sentido no realizar ninguna acción); no especificar ningún alcance implica que toda la entrada está dentro del alcance.
Al mismo tiempo, existe una superposición considerable con el simple tr
: la herramienta está diseñada para tener una estrecha correspondencia en los casos de uso más comunes y solo ir más allá cuando sea necesario.
La acción más sencilla es la sustitución. Se accede a él especialmente (como argumento, no como opción) por compatibilidad con tr
y ergonomía general. Todas las demás acciones se dan como banderas u opciones en caso de que tomen un valor.
Por ejemplo, los reemplazos simples de un solo carácter funcionan como en tr
:
$ echo ' Hello, World! ' | srgn ' H ' ' J '
Jello, World!
El primer argumento es el alcance (literal H
en este caso). Todo lo que coincida con él está sujeto a procesamiento (reemplazo por J
, el segundo argumento, en este caso). Sin embargo, no existe un concepto directo de clases de caracteres como en tr
. En cambio, de forma predeterminada, el alcance es un patrón de expresión regular, por lo que sus clases se pueden usar con un efecto similar:
$ echo ' Hello, World! ' | srgn ' [a-z] ' ' _ '
H____, W____!
El reemplazo se produce con avidez durante toda la partida de forma predeterminada (tenga en cuenta la clase de caracteres UTS, que recuerda a tr
's [:alnum:]
):
$ echo ' ghp_oHn0As3cr3T!! ' | srgn ' ghp_[[:alnum:]]+ ' ' * ' # A GitHub token
*!!
Se admiten funciones de expresiones regulares avanzadas, por ejemplo, búsquedas:
$ echo ' ghp_oHn0As3cr3T ' | srgn ' (?<=ghp_)[[:alnum:]]+ ' ' * '
ghp_*
Tenga cuidado al utilizarlos de forma segura, ya que los patrones avanzados no cuentan con ciertas garantías de seguridad y rendimiento. Si no se utilizan, el rendimiento no se ve afectado.
La sustitución no se limita a un solo carácter. Puede ser cualquier cadena, por ejemplo para corregir esta cita:
$ echo ' "Using regex, I now have no issues." ' | srgn ' no issues ' ' 2 problems '
"Using regex, I now have 2 problems."
La herramienta es totalmente compatible con Unicode y ofrece soporte útil para determinadas clases de caracteres avanzadas:
$ echo ' Mood: ? ' | srgn ' ? ' ' ? '
Mood: ?
$ echo ' Mood: ???? :( ' | srgn ' p{Emoji_Presentation} ' ' ? '
Mood: ???? :(
Los reemplazos conocen las variables, a las que se puede acceder para su uso a través de grupos de captura de expresiones regulares. Los grupos de captura se pueden numerar o, opcionalmente, nombrar. El grupo de captura cero corresponde a todo el partido.
$ 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.
Un caso de uso más avanzado es, por ejemplo, la refactorización de código utilizando grupos de captura con nombre (tal vez se le ocurra uno más útil...):
$ echo ' let x = 3; ' | srgn ' let (?[a-z]+) = (?.+); ' ' const $var$var = $expr + $expr; '
const xx = 3 + 3;
Al igual que en bash, utilice llaves para eliminar la ambigüedad de las variables del contenido inmediatamente adyacente:
$ 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)
Al ver que el reemplazo es simplemente una cadena estática, su utilidad es limitada. Aquí es donde normalmente entra en juego la salsa secreta de tr
: usar sus clases de caracteres, que también son válidas en la segunda posición, traduciendo claramente de los miembros de la primera a la segunda. Aquí, esas clases son expresiones regulares y solo son válidas en la primera posición (el alcance). Al ser una expresión regular una máquina de estados, es imposible hacer coincidir una 'lista de caracteres', que en tr
es el segundo argumento (opcional). Ese concepto ha desaparecido y se ha perdido su flexibilidad.
En su lugar se utilizan las acciones ofrecidas, todas ellas fijas . Un vistazo a los casos de uso más comunes de tr
revela que el conjunto de acciones proporcionado cubre prácticamente todos ellos. No dude en presentar un problema si su caso de uso no está cubierto.
A la siguiente acción.
Elimina todo lo que se encuentra en la entrada. Mismo nombre de bandera que en tr
.
$ echo ' Hello, World! ' | srgn -d ' (H|W|!) '
ello, orld
Nota
Como el alcance predeterminado es coincidir con toda la entrada, es un error especificar la eliminación sin un alcance.
Comprime las repeticiones de caracteres que coinciden con el alcance en apariciones únicas. Mismo nombre de bandera que en tr
.
$ echo ' Helloooo Woooorld!!! ' | srgn -s ' (o|!) '
Hello World!
Si se pasa una clase de personaje, todos los miembros de esa clase se agrupan en cualquier miembro de la clase que se haya encontrado primero:
$ echo ' The number is: 3490834 ' | srgn -s ' d '
The number is: 3
La codicia en el emparejamiento no se modifica, así que tenga cuidado:
$ echo ' Winter is coming... ??? ' | srgn -s ' ?+ '
Winter is coming... ???
Nota
El patrón coincidía con toda la serie de soles, por lo que no hay nada que exprimir. Prevalece el verano.
Invierta la avaricia si el caso de uso lo requiere:
$ echo ' Winter is coming... ??? ' | srgn -s ' ?+? ' ' ☃️ '
Winter is coming... ☃️
Nota
Nuevamente, al igual que con la eliminación, especificar la compresión sin un alcance explícito es un error. De lo contrario, se comprime toda la entrada.
Una buena parte del uso tr
entra en esta categoría. Es muy sencillo.
$ echo ' Hello, World! ' | srgn --lower
hello, world!
$ echo ' Hello, World! ' | srgn --upper
HELLO, WORLD!
$ echo ' hello, world! ' | srgn --titlecase
Hello, World!
Descompone la entrada de acuerdo con el Formulario de normalización D y luego descarta los puntos de código de la categoría Marca (ver ejemplos). Eso significa a grandes rasgos: adoptar un carácter elegante, arrancar los trozos que cuelgan y tirarlos a la basura.
$ 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
Observe cómo mgła
está fuera del alcance de NFD, ya que es "atómico" y, por lo tanto, no se puede descomponer (al menos eso es lo que ChatGPT me susurra al oído).
Esta acción reemplaza los símbolos ASCII de varios caracteres con sus equivalentes Unicode nativos de punto de código único apropiados.
$ echo ' (A --> B) != C --- obviously ' | srgn --symbols
(A ⟶ B) ≠ C — obviously
Alternativamente, si solo te interesan las matemáticas, utiliza el alcance:
$ echo ' A <= B --- More is--obviously--possible ' | srgn --symbols ' <= '
A ≤ B --- More is--obviously--possible
Como existe una correspondencia 1:1 entre un símbolo ASCII y su reemplazo, el efecto es reversible 2 :
$ echo ' A ⇒ B ' | srgn --symbols --invert
A => B
Por el momento, solo se admite un conjunto limitado de símbolos, pero se pueden agregar más.
Esta acción reemplaza la ortografía alternativa de los caracteres especiales alemanes (ae, oe, ue, ss) por sus versiones nativas (ä, ö, ü, ß) 3 .
$ echo ' Gruess Gott, Neueroeffnungen, Poeten und Abenteuergruetze! ' | srgn --german
Grüß Gott, Neueröffnungen, Poeten und Abenteuergrütze!
Esta acción se basa en una lista de palabras (compile sin la función german
si esto sobrecarga demasiado su binario). Tenga en cuenta las siguientes características sobre el ejemplo anterior:
Poeten
permaneció como está, en lugar de ser convertido ingenua y erróneamente a Pöten
Abenteuergrütze
no se encontrará en ninguna lista de palabras razonable, pero de todos modos se trató correctamenteAbenteuer
también permaneció como está, en lugar de convertirse incorrectamente a Abenteür
Neueroeffnungen
forma furtivamente un elemento ue
que ninguna palabra constituyente ( neu
, Eröffnungen
) posee, pero aún así se procesa correctamente (a pesar de que las minúsculas también no coinciden)A petición, se pueden forzar reemplazos, lo cual es potencialmente útil para los nombres:
$ echo ' Frau Loetter steht ueber der Mauer. ' | srgn --german-naive ' (?<=Frau )w+ '
Frau Lötter steht ueber der Mauer.
A través de una mirada positiva hacia adelante, nada más que el saludo fue abarcado y por lo tanto cambiado. Mauer
permaneció correctamente como está, pero ueber
no fue procesado. Una segunda pasada soluciona esto:
$ echo ' Frau Loetter steht ueber der Mauer. ' | srgn --german-naive ' (?<=Frau )w+ ' | srgn --german
Frau Lötter steht über der Mauer.
Nota
Las opciones y marcas pertenecientes a algún "padre" tienen el prefijo del nombre de su padre, e implicarán su padre cuando se proporcionen, de modo que no es necesario pasar este último explícitamente. Es por eso que --german-naive
se nombra tal como está y no es necesario aprobar --german
.
Este comportamiento podría cambiar una vez que clap
admita el encadenamiento de subcomandos.
Algunas ramas son indecidibles para esta modesta herramienta, ya que opera sin contexto lingüístico. Por ejemplo, tanto Busse
(autobuses) como Buße
(penitencia) son palabras legales. De forma predeterminada, los reemplazos se realizan con avidez si son legales (ese es el objetivo de srgn
, después de todo), pero hay una bandera para alternar este comportamiento:
$ echo ' Busse und Geluebte ' | srgn --german
Buße und Gelübte
$ echo ' Busse ? und Fussgaenger ?♀️ ' | srgn --german-prefer-original
Busse ? und Fußgänger ?♀️
La mayoría de las acciones se pueden componer, a menos que hacerlo no tenga sentido (como la eliminación). Su orden de aplicación es fijo, por lo que el orden de las banderas dadas no tiene influencia (una alternativa, si es necesario, colocar tuberías en varios tramos). Los reemplazos siempre ocurren primero. Generalmente, la CLI está diseñada para evitar mal uso y sorpresas: prefiere fallar a hacer algo inesperado (lo cual es subjetivo, por supuesto). Tenga en cuenta que muchas combinaciones son técnicamente posibles, pero pueden producir resultados sin sentido.
La combinación de acciones podría verse así:
$ echo ' Koeffizienten != Bruecken... ' | srgn -Sgu
KOEFFIZIENTEN ≠ BRÜCKEN...
Se puede especificar un alcance más limitado, que se aplicará a todas las acciones por igual:
$ echo ' Koeffizienten != Bruecken... ' | srgn -Sgu ' bw{1,8}b '
Koeffizienten != BRÜCKEN...
Los límites de las palabras son obligatorios; de lo contrario, Koeffizienten
coincide con Koeffizi
y enten
. Tenga en cuenta que los períodos finales no se pueden, por ejemplo, comprimir. El alcance requerido de .
interferiría con el dado. La tubería regular resuelve esto:
$ echo ' Koeffizienten != Bruecken... ' | srgn -Sgu ' bw{1,8}b ' | srgn -s ' . '
Koeffizienten != BRÜCKEN.
Nota: el escape de expresiones regulares ( .
) se puede evitar mediante el alcance literal. La acción sustitutiva especialmente tratada también es componible:
$ echo ' Mooood: ????!!! ' | srgn -s ' p{Emoji} ' ' ? '
Mooood: ?!!!
Primero se reemplazan todos los emojis y luego se comprimen. Observe cómo no se exprime nada más.
Los visores son el segundo concepto de conducción de srgn
. En el caso predeterminado, el ámbito principal es una expresión regular. La sección de acciones mostró este caso de uso con cierto detalle, por lo que no se repite aquí. Se presenta como un primer argumento posicional.
srgn
extiende esto a través de ámbitos preparados y conscientes de la gramática del lenguaje, lo que es posible gracias a la excelente biblioteca tree-sitter
. Ofrece una función de consultas, que funciona de manera muy similar a la comparación de patrones con una estructura de datos de árbol.
srgn
viene incluido con algunas de las consultas más útiles. A través de su API reconocible (ya sea como biblioteca o mediante CLI, srgn --help
), uno puede conocer los idiomas admitidos y las consultas preparadas disponibles. Cada idioma admitido viene con una trampilla de escape, que le permite ejecutar sus propias consultas ad hoc personalizadas. El sombreado viene en forma de --lang-query
, donde lang
es un lenguaje como python
. Consulte a continuación para obtener más información sobre este tema avanzado.
Nota
Los ámbitos del lenguaje se aplican primero , por lo que cualquier expresión regular, también conocida como alcance principal, que pase, opera en cada construcción de lenguaje coincidente individualmente.
Esta sección muestra ejemplos de algunas de las consultas preparadas .
unsafe
(Rust) Una ventaja de la palabra clave unsafe
en Rust es su "grepabilidad". Sin embargo, un rg 'unsafe'
por supuesto, mostrará todas las coincidencias de cadenas ( rg 'bunsafeb'
ayuda hasta cierto punto), no solo aquellas en la palabra clave real del lenguaje Rust. srgn
ayuda a que esto sea más preciso. Por ejemplo:
// 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 ) ;
}
}
se puede buscar como