¿Cómo obtengo los 6 dígitos del medio de la ruta de un archivo?

¿Cómo obtengo los 6 dígitos del medio de la ruta de un archivo?

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é sedy awkfracasé.

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.tgzen el directorio /dbfs/mnt/dlg2stage/foldername/backupnameusando un bucle de shell:

for pathname in /dbfs/mnt/dlg2stage/foldername/backupname/*_*.tar.tgz; do
    name=$( basename "$pathname" )
    printf '%s\n' "${name%%_*}"
done

La basenameutilidad 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.tgza 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 $varque Madjunta el patrón.

POSIXly, puedes usar:

first_6_digits_of_file_tail=$(
  LC_ALL=C expr "/$file" : '.*/\([0-9]\{6\}\)[^/]*/*$'
)

LC_ALL=Cignorar 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 zshdonde 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 $fileque comienzan con operadores -o parecen exproperadores 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 /XXXXXXexcepto al final obtenga el mismo comportamiento que las soluciones que usan basenameo zsh $file:tdonde 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 201906dada 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

información relacionada