Obtém apenas o segundo último argumento do comando anterior

3
[ -f /root/.bash_aliases ] || echo "$_"

me dá ]

Eu quero /root/.bash_aliases

Eu também tentei

[ -f /root/.bash_aliases ] || echo !:2

mas isso me dá o seguinte resultado

[ -f /root/.bash_aliases ] || echo /root/.bash_aliases
/root/.bash_aliases

Eu só quero /root/.bash_aliases

    
por GypsyCosmonaut 23.09.2017 / 08:26

2 respostas

4

Esse é o tipo de coisa que as funções são feitas para:

print_if_not_regular() {
  [ -f "$1" ] || printf '%s\n' "$1"
}
print_if_not_regular /root/.bash_aliases

Algumas conchas como es ou zsh têm funções anônimas:

(){[ -f "$1" ] || printf '%s\n' $1} /root/.bash_aliases # zsh
@ {[ -f $1 ] || printf '%s\n' $1} /root/.bash_aliases # es

Eu evitaria usar $_ . Não funciona mais se você tiver uma armadilha DEBUG por exemplo.

$ bash -c 'trap ": \"\$((cmdcount+=1))\"" DEBUG; echo foo; echo "$_"'
foo
2

Note que !:n não é o argumento n th do último comando, mas o n th token léxico da linha de comando anterior (a última linha (possivelmente mesmo multilinha) armazenada na história). Por exemplo, em

echo $(echo A B)
echo foo; echo !:1

Esse !:1 não é expandido para foo (o último argumento do último comando), nem B (o último argumento do comando echo do comando echo da linha de comando anterior), mas $(echo A B) . Aqui você precisa inserir:

[ -f /root/.bash_aliases ] ||
  echo !:2

Isto é, insira-o em linhas separadas. Aqui, acontece de funcionar (por acidente) mesmo que a linha do histórico não esteja totalmente concluída no momento em que você entra na segunda linha. Esse mesmo truque não funciona em (t)csh (de onde vem as expansões do histórico), nem em zsh .

    
por 23.09.2017 / 08:54
3

Use

test -f /root/.bash_aliases || echo "$_"

ou

test -f /root/.bash_aliases || printf '%s\n' "$_"

$_ será expandido para o último argumento do comando anterior. No seu exemplo, o comando anterior é [ e seu último argumento é ] .

Acima, o último comando é test e seu último argumento é o nome do arquivo.

test e [ são os mesmos comandos, mas [ requer um ] como seu último argumento de linha de comando. Neste caso, é isso que torna difícil usar $_ para obter o nome do arquivo.

A solução acima tem o benefício de trabalhar em pelo menos bash (a menos que você tenha um conjunto% trap DEBUG ) e zsh .

Se você tem o nome do arquivo em uma variável, seria trivial fazer

[ -f "$name" ] || printf '%s\n' "$name"

ou

if [ ! -f "$name" ]; then
    printf '%s\n' "$name"
fi

dependendo de sua preferência por declarações if e testes lógicos de curto-circuito.

    
por 23.09.2017 / 08:30

Tags