Extraindo número do nome do arquivo

Extraindo número do nome do arquivo

Eu tenho um nome de arquivo seguindo este modelo:

 1.raw_bank_details_211.trg
 2.raw_bank_details_222.trg

Preciso usar o cutcomando no unix e cortar a string acima para obter 211 e 222das strings e ecoar o valor.

Já usei grep grep -o -E '[0-9]+', preciso de uma alternativa para isso.

Responder1

Seria melhor usar uma ferramenta de processamento de texto padrão em vez de uma ferramenta ingênua como o cut.

Aqui estão algumas maneiras:


Com awk, obtendo o penúltimo campo _ou separado:.

awk -F '[_.]' '{print $(NF-1)}' file.txt

grepcom PCRE ( -P):

grep -Po '\d+(?=[^_]*$)' file.txt
  • -oobtém apenas a parte correspondente

  • \d+corresponde a um ou mais dígitos

  • O lookahead positivo de largura zero, (?=[^_]*$), garante que não _siga até o final da linha


Com sed:

sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
  • .*_combina com tudo até o fim_

  • ([[:digit:]]+)corresponde aos dígitos necessários e colocado no grupo capturado

  • .*combina com o resto

  • Na substituição, apenas o grupo capturado, \1, é usado


Com perl, mesma lógica daquela sed:

perl -pe 's/.*_(\d+).*/$1/' file.txt 

Se você precisar usar cut, faça isso em duas etapas, primeiro _separe o 4º campo e depois .separe o 1º campo:

cut -d_ -f4 file.txt | cut -d. -f1

Isso não é recomendado, pois exige que os números dos campos sejam codificados.


Se fosse uma string, eu faria isso usando a expansão dos parâmetros do shell:

% str='1.raw_bank_details_211.trg'

% str=${str##*_} 

% echo "${str%%.*}"
211

Você ainda pode usar uma whileconstrução e transformar cada linha em uma variável e fazer isso, mas isso seria lento para um arquivo grande. Alternativamente, você também pode usar _.as IFSe obter o campo codificado (como cut), se desejar.


Exemplo:

% cat file.txt                          
1.raw_bank_details_211.trg
2.raw_bank_details_222.trg

% awk -F '[_.]' '{print $(NF-1)}' file.txt
211
222

% grep -Po '\d+(?=[^_]*$)' file.txt         
211
222

% sed -E 's/.*_([[:digit:]]+).*/\1/' file.txt
211
222

% perl -pe 's/.*_(\d+).*/$1/' file.txt 
211
222

% cut -d_ -f4 file.txt | cut -d. -f1
211
222

Responder2

cuté a ferramenta errada para isso. Para manipular strings curtas, como nomes de arquivos, use os recursos de manipulação de strings do shell sempre que possível. Todos os shells do tipo sh¹ (sh, dash, bash, ksh, zsh,…) possuem alguma manipulação básica de strings como parte da substituição de variáveis. Veja, por exemplo, omanual do painelem “expansão de parâmetros”. Você pode remover o prefixo/sufixo mais curto/mais longo que corresponde a um padrão.

Você deseja a última sequência de dígitos no nome do arquivo, então:

  1. Determine o sufixo não numérico eliminando tudo até o último dígito.
  2. Remova esse sufixo.
  3. Retire tudo até o último não dígito.
filename=1.raw_bank_details_211.trg
suffix="${filename##*[0-9]}"
number="${filename%"$suffix"}"
number="${number##*[!-0-9]}"

¹ Exceto alguns shells Bourne pré-POSIX, mas você não se importa com eles.

informação relacionada