
Eu tenho um nome de caminho de arquivo como
/dbfs/mnt/dlg2stage/foldername/backupname/201906_load_1_20210623-151602.tar.tgz
Estou tentando obter apenas os 201906
dígitos de seis dígitos e imprimi-los. Eu tentei sed
e awk
mas falhei.
Responder1
Supondo que esses arquivos sejam reais em seu sistema, você pode extrair facilmente a parte anterior à primeira _
nos nomes de arquivo de cada arquivo correspondente *_*.tar.tgz
no diretório /dbfs/mnt/dlg2stage/foldername/backupname
usando um loop de shell:
for pathname in /dbfs/mnt/dlg2stage/foldername/backupname/*_*.tar.tgz; do
name=$( basename "$pathname" )
printf '%s\n' "${name%%_*}"
done
O basename
utilitário fornecerá a parte do nome do arquivo de um nome de caminho. Dado o exemplo que você mostra, isso atribuiria a string 201906_load_1_20210623-151602.tar.tgz
à variável name
. Você também poderia ter feito name=${pathname##*/}
a mesma coisa (esta expansão de parâmetro remove a seção inicial da string em $pathname
, até e incluindo a última /
).
A expansão do parâmetro ${name%%_*}
resultaria na _*
remoção da correspondência de substring mais longa do valor $name
. Com o exemplo mostrado, isso removeria o primeiro _
caractere e tudo à direita dele, deixando a substring 201906
, que é então impressa usando printf
.
Responder2
Com 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)}
Onde ${file:t}
leva ocaudado arquivo (seu nome base), ${(M)var#pattern}
retorna a parte no início $var
que M
atribui o padrão.
POSIXly, você pode usar:
first_6_digits_of_file_tail=$(
LC_ALL=C expr "/$file" : '.*/\([0-9]\{6\}\)[^/]*/*$'
)
LC_ALL=C
ignorar a localidade do usuário e considerar todos os bytes como caracteres (os 128 primeiros conforme ASCII na maioria dos sistemas, incluindo / e 0123456789 dígitos) para que .
e [^/]
seja garantido que corresponda aos bytes e [0-9]
inclua apenas 0123456789. Não são dígitos zsh
onde os intervalos são baseados em codepoints e zsh consideram cada byte que não faz parte de caracteres válidos como se fosse um caractere.
Anexar /
para evitar problemas com valores $file
que começam com -
ou se parecem com expr
operadores e também para garantir que as strings contenham pelo menos um /
conforme esperado pelo regexp.
Não permitimos /
que s após o /XXXXXX
exceto no final obtenham o mesmo comportamento que soluções usando basename
or zsh $file:t
onde o nome base de /foo/bar/
or /foo/bar////
é bar
.
Cuidado, ele retorna um status de saída falso/falha se não houver correspondência, mas também se essa sequência de 6 dígitos representar o número 0 (como em /path/to/000000_whatever
).
Responder3
Eu acho que você só quer imprimir 201906
dada essa string de caminho. Nesse exemplo, esses seis dígitos são:os primeiros seis dígitos que têm uma barra na frente deles.
Estou colocando o caminho em uma variável apenas para facilitar a leitura do comando:
% path_str='/dbfs/mnt/dlg2stage/foldername/backupname/201906_load_1_20210623-151602.tar.tgz'
% echo $path_str | sed 's/.*\/\([0-9]\{6\}\).*/\1/'
201906
Veja como construí essa correspondência e substituição emsed:
\/[0-9]\{6\}
: corresponde a uma barra e 6 dígitos\/\([0-9]\{6\}\)
: é o mesmo, mas agora em umgrupo de capturaousubexpressão(a barra não está no grupo de captura).*\/\([0-9]\{6\}\).*
: combina com tudo antes e depois, então...toda a linha\1
: com toda a linha correspondida, use a referência para oprimeiro(e apenas) grupo de captura para substituir a linha inteira apenas pelos primeiros 6 dígitos