Gostaria de excluir o último caractere de uma string, tentei este pequeno script:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
mas imprime "lkj", o que estou fazendo de errado?
Gostaria de excluir o último caractere de uma string, tentei este pequeno script:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
mas imprime "lkj", o que estou fazendo de errado?
Respostas:
Em um shell POSIX, a sintaxe ${t:-2}
significa algo diferente - ela se expande para o valor de t
se t
for definido e não nulo e, caso contrário, para o valor 2
. Para aparar um único caractere por expansão de parâmetro, a sintaxe que você provavelmente deseja é${t%?}
Observe que em ksh93
, bash
ou zsh
, ${t:(-2)}
ou ${t: -2}
(observe o espaço) são legais como uma expansão de substring, mas provavelmente não é o que você deseja, pois eles retornam o substring começando com uma posição de 2 caracteres a partir do final (ou seja, ele remove o primeiro caractere i
do string ijk
).
Consulte a seção Expansão de parâmetros do shell do Manual de referência do Bash para obter mais informações:
${parameter%word}
remove a menor correspondência de padrão de sufixo word
- consulte a seção Expansão de parâmetro deman bash
Com bash
4.2 e acima, você pode fazer:
${var::-1}
Exemplo:
$ a=123
$ echo "${a::-1}"
12
Observe que para os mais antigos bash
(por exemplo, bash 3.2.5
no OS X), você deve deixar espaços entre dois pontos e depois:
${var: : -1}
bash
versão 4.2-alpha e acima, muito ruim a versão à qual tenho acesso é anterior. : - /
${var:offset:lenght}
foi adicionado apenas em bash 4.2
. Talvez o OSX adicione seu próprio patch para bash
.
para remover os últimos n
caracteres de uma linha que não utiliza sed
OR awk
:
> echo lkj | rev | cut -c (n+1)- | rev
portanto, por exemplo, você pode excluir o último caractere one character
usando este:
> echo lkj | rev | cut -c 2- | rev
> lk
da rev
página de manual:
DESCRIÇÃO
O utilitário rev copia os arquivos especificados para a saída padrão, revertendo a ordem dos caracteres em cada linha. Se nenhum arquivo for especificado, a entrada padrão será lida.
ATUALIZAR:
se você não souber o comprimento da string, tente:
$ x="lkj"
$ echo "${x%?}"
lk
Usando sed, deve ser tão rápido quanto
sed 's/.$//'
Seu único eco é então echo ljk | sed 's/.$//'
.
Usando isso, a cadeia de caracteres de 1 linha pode ter qualquer tamanho.
Algumas opções, dependendo do shell:
t=${t%?}
t=`expr " $t" : ' \(.*\).'`
t=${t[1,-2]}
t=${t:0:-1}
t=${t:0:${#t}-1}
t=${t/%?}
t=${t/~(E).$/}
@ {t=$1} ~~ $t *?
Observe que, embora todos devam remover o último caractere , você descobrirá que algumas implementações (aquelas que não suportam caracteres de vários bytes) retiram o último byte (portanto, isso provavelmente corromperá o último caractere se for multi-byte )
A expr
variante assume $t
que não termina em mais de um caractere de nova linha. Ele também retornará um status de saída diferente de zero se a sequência resultante acabar sendo 0
( 000
ou mesmo -0
com algumas implementações). Também pode fornecer resultados inesperados se a sequência contiver caracteres inválidos.
t=${t%?}
não é Bourne, mas você provavelmente não encontrará um shell Bourne hoje em dia. ${t%?}
funciona em todos os outros embora.
fish
é um trabalho em andamento. 2.3.0 que introduziu o string
built-in não foi lançado no momento das perguntas e respostas. Com a versão em que estou testando, você precisa string replace -r '(?s).\z' '' -- $t
(e eu espero que eles mudem isso, eles devem mudar as bandeiras que passam para o PCRE) ou mais complicadas. Também lida mal com caracteres de nova linha, e eu sei que eles estão planejando mudar isso também.
A resposta mais portátil e mais curta é quase certamente:
${t%?}
Isso funciona em bash, sh, ash, dash, busybox / ash, zsh, ksh, etc.
Ele funciona usando a expansão de parâmetros do shell da velha escola. Especificamente, %
especifica para remover o menor sufixo de parâmetro t
correspondente ao padrão glob ?
(ou seja: qualquer caractere).
Consulte "Remover o menor padrão de sufixo" aqui para obter uma explicação (muito) mais detalhada e mais informações. Veja também os documentos do seu shell (por exemplo man bash
:) em "expansão de parâmetros".
Como observação, se você deseja remover o primeiro caractere, use-o ${t#?}
, pois #
corresponde da frente da string (prefixo) em vez da parte traseira (sufixo).
Também digno de nota é que ambos %
e #
have %%
e ##
versões, que correspondem à versão mais longa do padrão fornecido, em vez da mais curta. Ambos ${t%%?}
e ${t##?}
fariam o mesmo que seu único operador nesse caso, no entanto (portanto, não adicione o caractere inútil). Isso ocorre porque o ?
padrão fornecido corresponde apenas a um único caractere. Misture um *
com alguns caracteres não curinga e as coisas ficam mais interessantes com %%
e ##
.
Compreender as expansões de parâmetros, ou pelo menos saber sobre sua existência e saber procurá-las, é incrivelmente útil para escrever e decifrar scripts de shell de vários tipos. As expansões de parâmetro costumam parecer vodu arcano para muitas pessoas porque ... bem ... são vodu arcano (embora muito bem documentado se você souber procurar "expansão de parâmetro"). Definitivamente, é bom ter o cinto de ferramentas quando você está preso em uma concha.
t=lkj
echo ${t:0:${#t}-1}
Você obtém uma substring de 0 ao comprimento da string -1. Observe, no entanto, que essa subtração é específica do bash e não funciona em outros shells.
Por exemplo, dash
não é capaz de analisar nem
echo ${t:0:$(expr ${#t} - 1)}
Por exemplo, no Ubuntu, /bin/sh
édash
Você também pode head
imprimir todos os caracteres, exceto o último.
$ s='i am a string'
$ news=$(echo -n $s | head -c -1)
$ echo $news
i am a strin
Infelizmente, porém, algumas versões head
do não incluem a -
opção principal . Este é o caso do head
que acompanha o OS X.
Apenas para concluir alguns usos possíveis do bash puro:
#!/bin/bash
# Testing substring removal
STR="Exemple string with trailing whitespace "
echo "'$STR'"
echo "Removed trailing whitespace: '${STR:0:${#STR}-1}'"
echo "Removed trailing whitespace: '${STR/%\ /}'"
A primeira sintaxe pega uma substring de uma string, a sintaxe é.
Para a segunda, observe o sinal, que significa 'do final da linha' e a sintaxe é
${STRING:OFFSET:LENGTH}
%
${STRING/PATTERN/SUBSTITUTION}
E aqui estão duas formas mais curtas do mencionado acima
echo "Removed trailing whitespace: '${STR::-1}'"
echo "Removed trailing whitespace: '${STR%\ }'"
Observe novamente o %
sinal, que significa 'Remover (ou seja, substitua por' ') o padrão de correspondência mais curto (aqui representado pelo espaço escapado ' \ ' do final do PARÂMETRO - aqui chamado STR