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