Hay muchas formas de reemplazar caracteres en una variable.
El camino más corto que descubrí es tr
hasta ahora:
OUTPUT=a\'b\"c\`d_123and_a_lot_more
OUTPUT=$(echo "$OUTPUT"|tr -d "'\`\"")
echo $OUTPUT
¿Hay una manera mas rápida? Y es este seguro citando a citas como '
, "
y `sí mismo?
tr
. La PE de BASH es buena, pero tr es mucho más rápida en este caso. por ejemplo,echo "$OUTPUT" | tr -dc '[[:alpha:]]'
ya que solo desea tener alfanuméricosecho "$OUTPUT"
. O mejor:printf "%s\n" "$OUTPUT"
. (¿Qué sucede cuándoOUTPUT="-n"
?)Respuestas:
Veamos. Lo más corto que se me ocurre es un ajuste de su
tr
solución:Otras alternativas incluyen la sustitución de variables ya mencionada que puede ser más corta que la mostrada hasta ahora:
Y,
sed
por supuesto, aunque esto es más largo en términos de caracteres:No estoy seguro de si te refieres a la longitud más corta o en términos de tiempo empleado. En términos de longitud, estos dos son lo más cortos posible (o como puedo obtener de todos modos) cuando se trata de eliminar esos caracteres específicos. Entonces, ¿cuál es el más rápido? Probé configurando la
OUTPUT
variable a lo que tenía en su ejemplo, pero repetí varias docenas de veces:Como puede ver, el
tr
es claramente el más rápido, seguido de cercased
. Además, parece que usarecho
es en realidad un poco más rápido que usar<<<
:Como la diferencia es pequeña, realicé las pruebas anteriores 10 veces para cada una de las dos y resulta que la más rápida es la que tenía que comenzar:
Sin embargo, esto cambia cuando tiene en cuenta la sobrecarga de asignar a una variable, aquí, el uso
tr
es un poco más lento que el reemplazo simple:Entonces, en conclusión, cuando simplemente desea ver los resultados, use
tr
pero si desea reasignar a una variable, usar las funciones de manipulación de cadenas del shell es más rápido ya que evitan la sobrecarga de ejecutar un subshell separado.fuente
OUTPUT
, tendrá que tener en cuenta la sobrecarga de sub-shell de sustitución de comandos involucradatr
y lassed
solucionesOUTPUT="${OUTPUT//[`\"\']/}"
no implica la sustitución de comandosPuedes usar la sustitución de variables :
Use esa sintaxis:
${parameter//pattern/string}
para reemplazar todas las apariciones del patrón con la cadena.fuente
echo ${OUTPUT//[`\"\']/x}
daaxbxcxa
En bash o zsh es:
Tenga en cuenta que
${VAR//PATTERN/}
elimina todas las instancias del patrón. Para más información expansión de parámetros bashEsta solución debería ser más rápida para cadenas cortas porque no implica ejecutar ningún programa externo. Sin embargo, para cadenas muy largas, ocurre lo contrario: es mejor usar una herramienta dedicada para operaciones de texto, por ejemplo:
fuente
tr
es más rápido. Regexes y globs son caros, y aunque no hay un programa externo aquí, bash siempre será más lento que algo asítr
.tr
gana (vea mi respuesta). Estoy de acuerdo en que dependerá de muchos factores, pero esa es exactamente la razón por la que no se puede saber cuál gana sin probarlo realmente.Si, por casualidad, solo está tratando de manejar las cotizaciones para reutilizar el shell, puede hacerlo sin eliminarlas, y también es muy simple:
Ese shell de funciones cita cualquier matriz arg que le entregue e incrementa su salida por argumento iterable.
Aquí está con algunos argumentos:
SALIDA
Esa salida es a partir de la
dash
cual, por lo general, las comillas seguras son comillas simples'"'"'
.bash
haría'\''
.Reemplazar una selección de bytes únicos, no espacios en blanco, no nulos con otro byte único probablemente se puede hacer más rápido en cualquier shell POSIX con
$IFS
y$*
.SALIDA
Ahí lo acabo de
printf
ver, pero por supuesto, si lo hubiera hecho:... en lugar del
printf
comando$var
sería lo que ves en la salida allí.Cuando le
set -f
indico al shell que no se meta, en el caso de que la cadena contenga caracteres que podrían interpretarse como patrones globales. Hago esto porque el analizador de shells expande los patrones globales después de realizar la división de campo en las variables. globbing se puede volver a habilitar comoset +f
. En general, en los scripts, me resulta útil configurar mi explosión como:Y luego habilitar explícitamente globbing con
set +f
cualquier línea que desee.La división de campos se produce en función de los caracteres en
$IFS
.Hay dos tipos de
$IFS
valores:$IFS
espacios en blanco y$IFS
no espacios en blanco.$IFS
los campos delimitados de espacios en blanco (espacio, tabulación, nueva línea) se especifican para eluir por secuencia a un solo campo (o ninguno en absoluto si no preceden a otra cosa) , así que ...Pero todos los demás están especificados para evaluar en un solo campo por ocurrencia ; no se truncan.
Todas las expansiones variables son, de forma predeterminada,
$IFS
matrices de datos delimitadas; se dividen en campos separados según$IFS
. Cuando"
cita una, anula esa propiedad de matriz y la evalúa como una sola cadena.Entonces cuando lo hago ...
Estoy configurando la matriz de argumentos del shell en los muchos
$IFS
campos delimitados generados por$var
la expansión de. Cuando se expande, sus valores constitutivos para los caracteres contenidos$IFS
se pierden , ahora son solo separadores de campo, lo son\0NUL
."$*"
- al igual que otras expansiones variables con comillas dobles - también anula las cualidades de división de campo de$IFS
. Pero, además , sustituye el primer byte$IFS
por cada campo delimitado en"$@"
. Así pues"
fue el primer valor en$IFS
todos los delimitadores posteriores se convierten"
en"$*"
. Y"
tampoco es necesario que lo separes$IFS
cuando lo dividas. Se podría alterar$IFS
despuésset -- $args
a otro valor en su totalidad y su nuevo primer byte A continuación, presentó a los delimitadores de campo en"$*"
. Además, puede eliminar todos los rastros de ellos por completo como:SALIDA
fuente
tr
en cualquier shell, pero la diferencia es dudosabash
para el${var//$c/$newc/}
caso. Espero que incluso en ese caso sea más rápido por algún margen, pero generalmente no me preocupo por eso porque para estas cosas siempre usodash
, que es más rápido por órdenes de magnitud en general en todos los aspectos. Y entonces es difícil de comparar.bash
hacer,time (IFS=\"\'`; set -- $var; printf %s "$*")
ytime (var=${var//\'`/\"/})
ambos resultan en0.0000s
resultados para todos los campos. ¿Estoy haciendo algo mal, crees? Se supone que debe haber una barra diagonal inversa antes de la cita anterior, pero no sé cómo poner una cita inversa en un campo de código de comentario.