
Tengo una ruta de archivo como
/dbfs/mnt/dlg2stage/foldername/backupname/201906_load_1_20210623-151602.tar.tgz
Estoy tratando de obtener solo los seis dígitos 201906
e imprimirlos. Lo intenté sed
y awk
fracasé.
Respuesta1
Suponiendo que estos son archivos reales en su sistema, puede extraer fácilmente la parte anterior a la primera _
en los nombres de archivo de cada archivo que coincida *_*.tar.tgz
en el directorio /dbfs/mnt/dlg2stage/foldername/backupname
usando un bucle de shell:
for pathname in /dbfs/mnt/dlg2stage/foldername/backupname/*_*.tar.tgz; do
name=$( basename "$pathname" )
printf '%s\n' "${name%%_*}"
done
La basename
utilidad le dará la parte del nombre de archivo de una ruta. Dado el ejemplo que muestras, esto asignaría la cadena 201906_load_1_20210623-151602.tar.tgz
a la variable name
. También podría haber utilizado name=${pathname##*/}
para hacer lo mismo (esta expansión de parámetro elimina la sección inicial de la cadena en $pathname
, hasta el último inclusive /
).
La expansión del parámetro ${name%%_*}
daría como resultado la _*
eliminación del valor de la subcadena final más larga que coincida $name
. Con el ejemplo mostrado, esto eliminaría el primer _
carácter y todo lo que está a su derecha, dejando la subcadena 201906
, que luego se imprime usando printf
.
Respuesta2
Con zsh
:
file=/dbfs/mnt/dlg2stage/foldername/backupname/201906_load_1_20210623-151602.tar.tgz
set -o extendedglob # for (#c6)
first_6_digits_of_file_tail=${(M)${file:t}[0-9](#c6)}
donde ${file:t}
toma elcoladel archivo (su nombre base), ${(M)var#pattern}
devuelve la parte al comienzo $var
que M
adjunta el patrón.
POSIXly, puedes usar:
first_6_digits_of_file_tail=$(
LC_ALL=C expr "/$file" : '.*/\([0-9]\{6\}\)[^/]*/*$'
)
LC_ALL=C
ignorar la configuración regional del usuario y considerar todos los bytes como caracteres (el 128 primero según ASCII en la mayoría de los sistemas, incluidos / y 0123456789 dígitos) para .
garantizar [^/]
que coincida con los bytes e [0-9]
incluya solo 0123456789. No son dígitos zsh
donde los rangos se basan en codepoints y zsh consideran cada byte que no forma parte de caracteres válidos como si fuera un carácter.
Anteponiendo /
para evitar problemas con valores $file
que comienzan con operadores -
o parecen expr
operadores y también para garantizar que las cadenas contengan al menos uno /
como lo espera la expresión regular.
No permitimos /
que s después de /XXXXXX
excepto al final obtenga el mismo comportamiento que las soluciones que usan basename
o zsh $file:t
donde el nombre base de /foo/bar/
o /foo/bar////
es bar
.
Tenga en cuenta que devuelve un estado de salida falso/fallido si no hay coincidencia pero también si esa secuencia de 6 dígitos representa el número 0 (como en /path/to/000000_whatever
).
Respuesta3
Creo que solo quieres imprimir 201906
dada esa cadena de ruta. En ese ejemplo, esos seis dígitos son:los primeros seis dígitos que tienen una barra delante de ellos.
Estoy poniendo la ruta en una variable solo para que el comando sea más fácil de leer:
% path_str='/dbfs/mnt/dlg2stage/foldername/backupname/201906_load_1_20210623-151602.tar.tgz'
% echo $path_str | sed 's/.*\/\([0-9]\{6\}\).*/\1/'
201906
Así es como construí esa coincidencia y reemplazo ensed:
\/[0-9]\{6\}
: coincide con una barra y 6 dígitos\/\([0-9]\{6\}\)
: es lo mismo, pero ahora en ungrupo de capturaosubexpresión(la barra diagonal no está en el grupo de captura).*\/\([0-9]\{6\}\).*
: coincide con todo antes y después, así que...toda la linea\1
: con toda la línea coincidente, use la referencia para elprimero(y único) grupo de captura para reemplazar toda la línea con solo los primeros 6 dígitos