He leído algunas otras preguntas sobre manipulación de cadenas de bash de tuberías, pero parecen ser aplicaciones especializadas.
Básicamente, ¿hay alguna manera de hacer lo siguiente más simple?
en vez de
$ string='hello world'; string2="${string// /_}"; echo "${string2^^}"
HELLO_WORLD
algo como
$ echo 'hello world' | $"{-// /_}" | "${ -^^}"
HELLO_WORLD
Editar Estoy interesado en permanecer dentro de las manipulaciones de bash si es posible para mantener la velocidad (a diferencia de sed / awk, que tienden a ralentizar mis scripts)
Edit2: @jimmij
Me gusta el segundo ejemplo y me llevó a hacer una función.
bash_m() { { read x; echo "${x// /_}"; } | { read x; echo "${x^^}"; }; }
echo hello world | bash_m
HELLO_WORLD
tr
manual, entonces lo contrario es cierto porque el tiempo de generación de los procesos es insignificante en comparación con el tiempo de manipulación de la cadena para la cualsed
yawk
son dedicados Si la cadena es extremadamente larga, diga todo el manual de bash, entonces bash puede negarse a continuar por completo, debido a algunas limitaciones internas.sed
,awk
,tr
o similares. Mire la respuesta gena2x, que edité hace algún tiempo agregando exactamente esta información: unix.stackexchange.com/questions/162221/... es posible que desee compararla con la respuesta terdon a la misma pregunta en la que da tiempo para cadenas cortas en las que el desove del proceso del caso lleva más tiempo. Puede probarlo usted mismo y publicar el resultado.read x; echo $x
es mejor para el rendimiento? La sintaxis no se ve más corta ni más limpia.x=${x// /_}; x=${x^^}
es una forma mucho más concisa de hacer lo mismo que{read x; echo ${x...
. En cuanto al rendimiento, @jimmij ha señalado quetr
/sed
sería más rápido quebash
, el recuento de horquillas es igual. Usar una tubería siempre resulta en un proceso adicional, por lo que el argumento de guardar una bifurcación ya no se aplica. Por lo tanto, si está utilizando tuberías, simplemente usesed
/tr
etc. Si puede hacerlo en bash, hágalo y omita estasread x; echo $x
tonterías.Respuestas:
Lo que dijo jimmij. Su último ejemplo es lo más cercano que puede llegar a lo que está intentando en su expresión canalizada.
Aquí hay una variante sobre ese tema:
Me inclinaría a usar
tr
, ya que es bastante rápido.Supongo que es una pena que bash no permita la expansión de parámetros anidados; OTOH, el uso de tales expresiones anidadas podría conducir fácilmente a un código que es doloroso de leer. A menos que realmente necesite que las cosas se ejecuten lo más rápido posible, es mejor escribir código que sea fácil de leer, comprender y mantener, en lugar de un código inteligente que es un PITA para depurar. Y si realmente necesita hacer las cosas a la máxima velocidad, debería usar código compilado, no un script.
fuente
No puede pasar expansiones de parámetros de esa manera. Cuando se refiere al
x
uso del$
símbolo como en el"${x}"
formulario, debe ser un nombre de variable real, no una entrada estándar, al menos no enbash
. Enzsh
puede realizar sustituciones de parámetros anidados de la siguiente manera:(nota:
:u
es parazsh
lo mismo que^^
parabash
)No es posible anidar en bash y creo que lo que escribiste en cuestión es lo mejor que puedes obtener, pero si por alguna extraña razón necesitas involucrar tuberías en la ecuación, entonces puedes intentar esto:
fuente
tr
/sed
son más rápidos quebash
en el procesamiento de cadenas, y considerando cómo está utilizando tuberías para pasar cadenas a través de E / S estándar, veo literalmente cero punto para hacer esas operaciones en bash en lugar detr
/sed
. ¿Por qué alguien en| { read x; echo $x... }
lugar de uno| sed
que hace lo mismo?echo
yread
son de bash muebles empotrados, por lo que, en principio, un poco más rápido). Como ya escribí en la respuesta, la manipulación progresiva de parámetros que OP tiene en la pregunta es lo mejor que puedo obtener en mi opinión para esta tarea en bash. De todos modos, el problema es bastante académico.