
Eu tenho um nome de arquivo seguindo este modelo:
1.raw_bank_details_211.trg
2.raw_bank_details_222.trg
Preciso usar o cut
comando no unix e cortar a string acima para obter 211
e 222
das 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
grep
com PCRE ( -P
):
grep -Po '\d+(?=[^_]*$)' file.txt
-o
obtém apenas a parte correspondente\d+
corresponde a um ou mais dígitosO 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 restoNa 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 while
construçã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 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:]]+).*/\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:
- Determine o sufixo não numérico eliminando tudo até o último dígito.
- Remova esse sufixo.
- 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.