Por exemplo, dado:
USCAGoleta9311734.5021-120.1287855805
Eu quero extrair apenas:
US
Por exemplo, dado:
USCAGoleta9311734.5021-120.1287855805
Eu quero extrair apenas:
US
Respostas:
Provavelmente, o método mais eficiente, se você estiver usando o bash
shell (e parece estar, com base nos seus comentários), é usar a variante de sub-string da expansão de parâmetros:
pax> long="USCAGol.blah.blah.blah"
pax> short="${long:0:2}" ; echo "${short}"
US
Isso definirá short
os dois primeiros caracteres de long
. Se long
for menor que dois caracteres, short
será idêntico a ele.
Esse método in-shell geralmente é melhor se você o fizer muito (como 50.000 vezes por relatório, como você mencionou), já que não há sobrecarga na criação do processo. Todas as soluções que usam programas externos sofrerão com essa sobrecarga.
Se você também deseja garantir um comprimento mínimo , pode prendê-lo antes da mão com algo como:
pax> long="A"
pax> tmpstr="${long}.."
pax> short="${tmpstr:0:2}" ; echo "${short}"
A.
Isso garantiria que algo com menos de dois caracteres fosse preenchido à direita com pontos (ou qualquer outra coisa, apenas alterando o caractere usado ao criar tmpstr
). Não está claro se você precisa disso, mas pensei em colocá-lo por completo.
Dito isto, existem várias maneiras de fazer isso com programas externos (como se você não tiver bash
disponível), algumas das quais são:
short=$(echo "${long}" | cut -c1-2)
short=$(echo "${long}" | head -c2)
short=$(echo "${long}" | awk '{print substr ($0, 0, 2)}'
short=$(echo "${long}" | sed 's/^\(..\).*/\1/')
Os dois primeiros ( cut
e head
) são idênticos para uma string de linha única - eles basicamente apenas devolvem os dois primeiros caracteres. Eles diferem no que cut
fornecerá os dois primeiros caracteres de cada linha e head
os dois primeiros caracteres de toda a entrada
O terceiro usa a awk
função sub-string para extrair os dois primeiros caracteres e o quarto usa sed
grupos de captura (usando ()
e \1
) para capturar os dois primeiros caracteres e substituir a linha inteira por eles. Ambos são semelhantes a cut
- eles entregam os dois primeiros caracteres de cada linha na entrada.
Nada disso importa se você tiver certeza de que sua entrada é uma única linha, todas elas têm um efeito idêntico.
printf '%s'
em vez de echo
no caso de existirem caracteres estranhos na string: stackoverflow.com/a/40423558/895245 Para o POSIX obcecado: head -c
não é POSIX, cut -c
e awk substr
são, sed \1
não tenho certeza.
maneira mais fácil é
${string:position:length}
Onde isso extrai a $length
substring de $string
em $position
.
Este é um bash embutido; portanto, awk ou sed não é necessário.
Você chegou várias respostas boas e eu iria com o Bash builtin mim mesmo, mas já que você perguntou sobre sed
e awk
e ( quase ) ninguém mais oferecido soluções com base neles, eu oferecer-lhe estes:
echo "USCAGoleta9311734.5021-120.1287855805" | awk '{print substr($0,0,2)}'
e
echo "USCAGoleta9311734.5021-120.1287855805" | sed 's/\(^..\).*/\1/'
O awk
primeiro deve ser bastante óbvio, mas aqui está uma explicação sed
:
substr($0,1,2)
.
Se você estiver dentro bash
, pode dizer:
bash-3.2$ var=abcd
bash-3.2$ echo ${var:0:2}
ab
Isso pode ser exatamente o que você precisa ...
Apenas grep:
echo 'abcdef' | grep -Po "^.." # ab
-P
opção para torná-la mais curta. Todos os regexs entenderão esse padrão.
Você pode usar printf
:
$ original='USCAGoleta9311734.5021-120.1287855805'
$ printf '%-.2s' "$original"
US
Muito tarde, de fato, mas aqui está
sed 's/.//3g'
Ou
awk NF=1 FPAT=..
Ou
perl -pe '$_=unpack a2'
Se você deseja usar scripts de shell e não confiar em extensões não-posix (como os chamados bashismos), você pode usar técnicas que não requerem bifurcação de ferramentas externas, como grep, sed, cut, awk etc., que então torne seu script menos eficiente. Talvez a eficiência e a portabilidade do posix não sejam importantes no seu caso de uso. Mas, caso seja (ou apenas um bom hábito), você pode usar o seguinte método de opção de expansão de parâmetro para extrair os dois primeiros caracteres de uma variável de shell:
$ sh -c 'var=abcde; echo "${var%${var#??}}"'
ab
Isso usa a expansão de parâmetro "menor prefixo" para remover os dois primeiros caracteres (esta é a ${var#??}
parte) e, em seguida, a expansão de parâmetro "menor sufixo" (a ${var%
parte) para remover a cadeia de caracteres com exceção de dois caracteres, exceto o primeiro valor.
Este método foi descrito anteriormente nesta resposta à pergunta "Shell = Verifique se a variável começa com #". Essa resposta também descreve alguns métodos de expansão de parâmetros semelhantes que podem ser usados em um contexto ligeiramente diferente daquele que se aplica à pergunta original aqui.
Se o seu sistema estiver usando um shell diferente (não bash
), mas o seu sistema tiver bash
, você ainda poderá usar a manipulação de string inerente bash
invocando bash
com uma variável:
strEcho='echo ${str:0:2}' # '${str:2}' if you want to skip the first two characters and keep the rest
bash -c "str=\"$strFull\";$strEcho;"
bash
se você ainda não o estiver usando.
Só por diversão, acrescentarei alguns que, apesar de complicados e inúteis, não foram mencionados:
head -c 2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
echo 'USCAGoleta9311734.5021-120.1287855805' | dd bs=2 count=1 status=none
sed -e 's/^\(.\{2\}\).*/\1/;' <( echo 'USCAGoleta9311734.5021-120.1287855805')
cut -c 1-2 <( echo 'USCAGoleta9311734.5021-120.1287855805')
python -c "print(r'USCAGoleta9311734.5021-120.1287855805'[0:2])"
ruby -e 'puts "USCAGoleta9311734.5021-120.1287855805"[0..1]'
se mystring = USCAGoleta9311734.5021-120.1287855805
print substr(mystring,0,2)
imprimiria EUA
onde 0 é a posição inicial e 2 é como meny chars para ler
awk
. Desculpe, eu não sabia dizer a princípio.
É isso que você procura?
my $string = 'USCAGoleta9311734.5021-120.1287855805';
my $first_two_chars = substr $string, 0, 2;
ref: substr
perl -e 'print substr $ARGV[0], 0, 2' 'USCAGoleta9311734.5021-120.1287855805'