Respostas:
Você pode usar operadores de string :
$ foo=1:2:3:4:5
$ echo ${foo##*:}
5
Isso apara tudo, desde a frente até um ':', avidamente.
${foo <-- from variable foo
## <-- greedy front trim
* <-- matches anything
: <-- until the last ':'
}
${foo%:*}
. #
- do começo; %
- do fim. #
, %
- menor correspondência; ##
, %%
- partida mais longa.
echo ${pwd##*/}
não funciona.
pwd
como uma variável. Tente dir=$(pwd); echo ${dir##*/}
. Funciona para mim!
Outra maneira é reverter antes e depois cut
:
$ echo ab:cd:ef | rev | cut -d: -f1 | rev
ef
Isso torna muito fácil obter o último, mas um campo, ou qualquer intervalo de campos numerados a partir do final.
echo "1 2 3 4" | rev | cut -d " " -f1 | rev
rev
, era exatamente o que eu precisava! cut -b20- | rev | cut -b10- | rev
É difícil obter o último campo usando o cut, mas aqui estão algumas soluções em awk e perl
echo 1:2:3:4:5 | awk -F: '{print $NF}'
echo 1:2:3:4:5 | perl -F: -wane 'print $F[-1]'
/
caractere de acabamento : /a/b/c/d
e /a/b/c/d/
produz o mesmo resultado ( d
) ao processar pwd | awk -F/ '{print $NF}'
. A resposta aceita resulta em um resultado vazio no caso de/a/b/c/d/
/
como delimitador e, se o seu caminho for, /my/path/dir/
ele usará o valor após o último delimitador, que é simplesmente uma string vazia. Portanto, é melhor evitar a barra se precisar fazer uma coisa como eu.
awk '{$NF=""; print $0}' FS=: OFS=:
muitas vezes funciona bem o suficiente.
Supondo um uso bastante simples (sem escape do delimitador, por exemplo), você pode usar grep:
$ echo "1:2:3:4:5" | grep -oE "[^:]+$"
5
Divisão - encontre todos os caracteres que não sejam o delimitador ([^:]) no final da linha ($). -o imprime apenas a parte correspondente.
Mão única:
var1="1:2:3:4:5"
var2=${var1##*:}
Outro, usando uma matriz:
var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
var2=${var2[@]: -1}
Ainda outro com uma matriz:
var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
count=${#var2[@]}
var2=${var2[$count-1]}
Usando expressões regulares do Bash (versão> = 3.2):
var1="1:2:3:4:5"
[[ $var1 =~ :([^:]*)$ ]]
var2=${BASH_REMATCH[1]}
$ echo "a b c d e" | tr ' ' '\n' | tail -1
e
Simplesmente traduza o delimitador em uma nova linha e escolha a última entrada com tail -1
.
\n
, mas na maioria dos casos é a solução mais legível.
Usando sed
:
$ echo '1:2:3:4:5' | sed 's/.*://' # => 5
$ echo '' | sed 's/.*://' # => (empty)
$ echo ':' | sed 's/.*://' # => (empty)
$ echo ':b' | sed 's/.*://' # => b
$ echo '::c' | sed 's/.*://' # => c
$ echo 'a' | sed 's/.*://' # => a
$ echo 'a:' | sed 's/.*://' # => (empty)
$ echo 'a:b' | sed 's/.*://' # => b
$ echo 'a::c' | sed 's/.*://' # => c
Se seu último campo for um único caractere, você poderá fazer o seguinte:
a="1:2:3:4:5"
echo ${a: -1}
echo ${a:(-1)}
Verifique a manipulação de strings no bash .
a
, não o último campo .
Há muitas boas respostas aqui, mas ainda quero compartilhar esta usando o nome de base :
basename $(echo "a:b:c:d:e" | tr ':' '/')
No entanto, ele falhará se já houver algum '/' na sua string . Se slash / é o seu delimitador, é necessário (e deve) usar o nome da base.
Não é a melhor resposta, mas apenas mostra como você pode ser criativo usando os comandos do bash.
Usando o Bash.
$ var1="1:2:3:4:0"
$ IFS=":"
$ set -- $var1
$ eval echo \$${#}
0
echo ${!#}
vez de eval echo \$${#}
.
for x in `echo $str | tr ";" "\n"`; do echo $x; done
Para aqueles que se sentem confortáveis com o Python, https://github.com/Russell91/pythonpy é uma boa opção para resolver este problema.
$ echo "a:b:c:d:e" | py -x 'x.split(":")[-1]'
Desde a ajuda pythonpy: -x treat each row of stdin as x
.
Com essa ferramenta, é fácil escrever código python que é aplicado à entrada.
Pode ser que seja um pouco tarde com a resposta, embora uma solução simples seja reverter a ordem da sequência de entrada. Isso permitiria que você sempre ganhasse o último item, independentemente do comprimento.
[chris@desktop bin]$ echo 1:2:3:4:5 | rev | cut -d: -f1
5
É importante observar que, se você usar esse método e os números forem maiores que 1 dígito (ou maiores que um caractere em qualquer circunstância), será necessário executar outro comando 'rev' sobre a saída canalizada.
[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1
42
[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1 | rev
24
Espero poder ajudar, felicidades
Se você gosta de python e tem uma opção para instalar um pacote, pode usar este utilitário python .
# install pythonp
pythonp -m pip install pythonp
echo "1:2:3:4:5" | pythonp "l.split(':')[-1]"
5
echo "1:2:3:4:5" | python -c "import sys; print(list(sys.stdin)[0].split(':')[-1])"
pythonp
pacote é fazer com que você faça as mesmas coisas que python -c
com menos tipos de caracteres. Por favor, dê uma olhada no README no repositório.
5
se a sequência for1:2:3:4:5:
(enquanto estiver usando os operadores de sequência produzirá um resultado vazio). Isso é especialmente útil ao analisar caminhos que podem conter (ou não) um/
caractere final .