Dado un nombre de archivo en el formulario someletters_12345_moreleters.ext
, quiero extraer los 5 dígitos y ponerlos en una variable.
Entonces, para enfatizar el punto, tengo un nombre de archivo con x número de caracteres, luego una secuencia de cinco dígitos rodeada por un solo guión bajo a cada lado y luego otro conjunto de x número de caracteres. Quiero tomar el número de 5 dígitos y ponerlo en una variable.
Estoy muy interesado en la cantidad de formas diferentes en que esto se puede lograr.
abc_12345_def_67890_ghi_def
es una entrada válida. ¿Qué es lo que desea que suceda? Supongamos que solo hay una secuencia de 5 dígitos. Todavía tieneabc_def_12345_ghi_jkl
o1234567_12345_1234567
o12345d_12345_12345e
como entrada válida basada en su definición de la entrada y la mayor parte de las respuestas a continuación no va a manejar esto._
delimitador, entrada que contiene la cadena de destino solo una vez, etc.). La mejor respuesta (la más genérica y más rápida) tiene, después de 10 años, solo 7 votos a favor, mientras que otras respuestas limitadas tienen cientos. Me hace perder la fe en los desarrolladores 😞Respuestas:
Usar corte :
Más genérico:
fuente
echo
menos que sepa con certeza que las variables no pueden contener espacios en blanco irregulares o metacaracteres de shell. Ver más stackoverflow.com/questions/10067266/…Si x es constante, la siguiente expansión de parámetros realiza la extracción de subcadenas:
donde 12 es el desplazamiento (basado en cero) y 5 es la longitud
Si los guiones bajos alrededor de los dígitos son los únicos en la entrada, puede quitar el prefijo y el sufijo (respectivamente) en dos pasos:
Si hay otros guiones bajos, probablemente sea factible de todos modos, aunque más complicado. Si alguien sabe cómo realizar ambas expansiones en una sola expresión, me gustaría saber también.
Ambas soluciones presentadas son puro bash, sin proceso de generación involucrado, por lo tanto, muy rápido.
fuente
bash: ${${a#*_}%_*}: bad substitution
en mi GNU bash 4.2.45.sh
script, que probablemente era un guión. En este punto ya no puedo hacer que funcione.:-
sustitución de "Usar valores predeterminados". Entonces${a: -12:5}
produce los 5 caracteres a 12 caracteres del final, y${a: -12:-5}
los 7 caracteres entre el final 12 y el final 5.Solución genérica donde el número puede estar en cualquier parte del nombre del archivo, utilizando la primera de tales secuencias:
Otra solución para extraer exactamente una parte de una variable:
Si su nombre de archivo siempre tiene el formato
stuff_digits_...
, puede usar awk:Otra solución más para eliminar todo, excepto los dígitos, usar
fuente
solo trata de usar
cut -c startIndx-stopIndx
fuente
startIndx-$((lastIndx-1))
start=5;stop=9; echo "the rain in spain" | cut -c $start-$(($stop-1))
git log --oneline | head -1 | cut -c 9-(end -1)
line=
divide en dos partes como git log --oneline | head -1` && echo $ line | cut -c 9 - $ (($ {# line} -1)) `pero en este caso particular, podría ser mejor usar sed comogit log --oneline | head -1 | sed -e 's/^[a-z0-9]* //g'
En caso de que alguien quiera información más rigurosa, también puede buscarla en man bash como este
Resultado:
fuente
${var: -4}
Así es como lo haría:
Explicación:
Específico de golpe:
[[ ]]
indica una expresión condicional=~
indica que la condición es una expresión regular&&
encadena los comandos si el comando anterior fue exitosoExpresiones regulares (RE):
_([[:digit:]]{5})_
_
son literales para demarcar / anclar límites coincidentes para la cadena que se está haciendo coincidir()
crear un grupo de captura[[:digit:]]
es una clase de personaje, creo que habla por sí mismo{5}
significa exactamente cinco del carácter anterior, clase (como en este ejemplo) o grupo debe coincidirEn inglés, puede pensar que se comporta así: la
FN
cadena se repite carácter por carácter hasta que veamos un_
punto en el que se abre el grupo de captura e intentamos hacer coincidir cinco dígitos. Si esa coincidencia es exitosa hasta este punto, el grupo de captura guarda los cinco dígitos recorridos. Si el siguiente carácter es un_
, la condición es exitosa, el grupo de captura está disponibleBASH_REMATCH
y la siguienteNUM=
instrucción puede ejecutarse. Si alguna parte de la coincidencia falla, los detalles guardados se eliminan y el procesamiento de carácter por carácter continúa después de_
. por ejemplo, siFN
dónde_1 _12 _123 _1234 _12345_
, habría cuatro comienzos falsos antes de encontrar una coincidencia.fuente
cut
). Tampoco se basa en ejecutar un comando externo.Me sorprende que esta solución pura de bash no haya aparecido:
¡Probablemente quiera restablecer IFS a su valor anterior o
unset IFS
posterior!fuente
IFS
y parámetros posicionales:IFS=_ read -r _ digs _ <<< "$a"; echo "$digs"
Sobre la base de la respuesta de jor (que no funciona para mí):
fuente
cut
lo hará .Siguiendo los requisitos
Encontré algunas
grep
formas que pueden ser útiles:o mejor
Y luego con
-Po
sintaxis:O si desea que se ajuste exactamente a 5 caracteres:
Finalmente, para que se almacene en una variable solo es necesario usar la
var=$(command)
sintaxis.fuente
Invocation as 'egrep' is deprecated; use 'grep -E' instead
. He editado tu respuesta.Si nos centramos en el concepto de:
"Una serie de (uno o varios) dígitos"
Podríamos usar varias herramientas externas para extraer los números.
Podríamos borrar fácilmente todos los demás caracteres, ya sea sed o tr:
Pero si $ name contiene varias series de números, lo anterior fallará:
Si "name = someletters_12345_moreleters_323_end.ext", entonces:
Necesitamos usar expresiones regulares (regex).
Para seleccionar solo la primera ejecución (12345 no 323) en sed y perl:
Pero también podríamos hacerlo directamente en bash (1) :
Esto nos permite extraer la PRIMERA serie de dígitos de cualquier longitud
rodeados por cualquier otro texto / carácter.
Nota :
regex=[^0-9]*([0-9]{5,5}).*$;
solo coincidirá con ejecuciones de exactamente 5 dígitos. :-)(1) : más rápido que llamar a una herramienta externa para cada texto breve. No más rápido que hacer todo el procesamiento dentro de sed o awk para archivos grandes.
fuente
Sin ningún subproceso puedes:
Una variante muy pequeña de esto también funcionará en ksh93.
fuente
Aquí hay una solución de prefijo-sufijo (similar a las soluciones proporcionadas por JB y Darron) que coincide con el primer bloque de dígitos y no depende de los guiones bajos circundantes:
fuente
Me encanta
sed
la capacidad de tratar con grupos de expresiones regulares:Una opción un poco más general sería no asumir que usted tiene un guión
_
que marca el inicio de su secuencia de dígitos, por lo tanto, por ejemplo despojarse de todos los no-números que se obtienen antes de que su secuencia:s/[^0-9]\+\([0-9]\+\).*/\1/p
.Más sobre esto, en caso de que no estés demasiado seguro con regexps:
s
es para _s_ubstitute[0-9]+
coincide con 1+ dígitos\1
enlaces al grupo n. 1 de la salida de expresiones regulares (el grupo 0 es la coincidencia completa, el grupo 1 es la coincidencia entre paréntesis en este caso)p
la bandera es para _p_rintingTodos los escapes
\
están ahí para hacer quesed
el procesamiento regexp funcione.fuente
Mi respuesta tendrá más control sobre lo que quieres de tu cadena. Aquí está el código sobre cómo puede extraer
12345
de su cadenaEsto será más eficiente si desea extraer algo que tenga caracteres como
abc
o caracteres especiales como_
o-
. Por ejemplo: si su cadena es así y desea todo lo que está despuéssomeletters_
y antes_moreleters.ext
:Con mi código puedes mencionar exactamente lo que quieres. Explicación:
#*
Eliminará la cadena anterior, incluida la clave correspondiente. Aquí la clave que mencionamos es_
%
Eliminará la siguiente cadena, incluida la clave correspondiente. Aquí la clave que mencionamos es '_more *'Haga algunos experimentos usted mismo y le parecerá interesante.
fuente
Dado test.txt es un archivo que contiene "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
fuente
Ok, aquí va la sustitución de parámetros pura con una cadena vacía. La advertencia es que he definido algunas letras y más letras como solo caracteres. Si son alfanuméricos, esto no funcionará como está.
fuente
similar a substr ('abcdefg', 2-1, 3) en php:
fuente
También está el comando bash builtin 'expr':
fuente
expr
No es una construcción.=~
operador admitido por[[
.Un poco tarde, pero me encontré con este problema y encontré lo siguiente:
Lo utilicé para obtener una resolución de milisegundos en un sistema integrado que no tiene% N para la fecha:
fuente
Una solución bash:
Esto golpeará una variable llamada
x
. La varx
se puede cambiar a la var_
.fuente
Fin Inklusive, similar a las implementaciones JS y Java. Elimina +1 si no deseas esto.
Ejemplo:
Más ejemplos de llamadas:
De nada.
fuente