Extraindo número do nome do arquivo

3

Eu tenho um nome de arquivo seguindo este modelo:

 1.raw_bank_details_211.trg
 2.raw_bank_details_222.trg

Eu preciso usar o comando cut no unix e cortar a string acima para obter 211 e 222 das strings e ecoar o valor.

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

    
por Rak kundra 25.04.2017 / 16:34

2 respostas

0

cut é a ferramenta errada para isso. Para manipular strings curtas, como nomes de arquivos, use as facilidades de manipulação de strings do shell sempre que possível. Todas as shells 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 o manual do traço em "expansão de parâmetro". Você pode remover o prefixo / sufixo mais curto / mais longo que corresponda 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, separando tudo até o último dígito.
  2. Remover esse sufixo.
  3. Distribua tudo até o último dígito não.
filename=1.raw_bank_details_211.trg
suffix="${filename##*[0-9]}"
number="${filename%"$suffix"}"
number="${number##*[!-0-9]}"

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

    
por 26.04.2017 / 01:29
3

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

Aqui estão algumas maneiras:

Com awk , a obtenção do _ ou . separou o segundo último campo:

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

grep com PCRE ( -P ):

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

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

  • A antecipação positiva da largura zero, (?=[^_]*$) , garante que nenhum _ esteja seguindo até o final da linha

com sed :

sed -E 's/.*_([[:digit:]]+).*//' file.txt
  • .*_ corresponde a tudo até o último _

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

  • .* corresponde ao restante

  • Na substituição, somente o grupo capturado, , é usado

Com perl , mesma lógica para o sed one:

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

Se você precisar usar cut , faça isso em duas etapas, primeiro obtenha o quarto campo _ separado e, em seguida, obtenha o primeiro campo . :

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

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

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

% str='1.raw_bank_details_211.trg'

% str=${str##*_} 

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

Você ainda pode usar uma construção while e usar cada linha em uma variável e fazer isso, mas isso seria lento para um arquivo grande. Você também pode usar alternadamente _. como IFS e 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:]]+).*//' file.txt
211
222

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

% cut -d_ -f4 file.txt | cut -d. -f1
211
222
    
por 25.04.2017 / 16:51