Come eseguo più comandi usando lo stesso argomento?


16

Mi chiedo se sia possibile effettuare azioni a catena nel terminale Ubuntu come:

action 1 on objectA . then action 2 on objectA 

senza dover ripetere più il nome dell'oggetto A.

Esempio:

touch file.js && openEditor "$1" 

o qualcosa di simile.


Ci sono molti modi per farlo, ma dipende dalle tue esigenze. Qual è l'oggetto A? un file ? Di quali azioni stiamo parlando?
Sergiy Kolodyazhnyy,

grazie, di solito un file efficace, può anche essere una cartella
HoCo_

3
Qui, &invierà il comando "touch" in background. Se intendevi "aprire l'editor se il tocco è riuscito", allora vuoi &&invece
glenn jackman,

Perché stai sbattendo questo post? Hai già ricevuto molte risposte e ne hai persino accettata una.
muru

Risposte:


27

Con bash History Expansion , puoi fare riferimento all'ennesima parola della riga di comando corrente usando !#:nad es

$ touch foobar && ls -l !#:1
touch foobar && ls -l foobar
-rw-rw---- 1 steeldriver steeldriver 0 Jun 20 14:54 foobar

$ touch foo bar && ls -l !#:2
touch foo bar && ls -l bar
-rw-rw-r-- 1 steeldriver steeldriver 12 Jun 20 14:58 bar

Posso chiederti quale versione bash stai usando?
Sergiy Kolodyazhnyy,

@SergiyKolodyazhnyy this isGNU bash, version 4.3.48(1)-release
steeldriver

5
puoi anche designare una serie di parole :touch foo bar && ls -l !#:1-2
glenn jackman,

1
@HoCo_ il !personaggio introduce un'espressione di espansione della cronologia quando ci si trova in una shell interattiva - è pensata per la manipolazione al volo della riga di comando durante la digitazione ed è disabilitata all'interno di script non interattivi
steeldriver

1
@HoCo_ in uno script dovresti sapere qual è l'argomento in anticipo - quindi ad esempio potresti semplicemente farearg1=file.js; touch "$arg1" && openEditor "$arg1"
steeldriver

12

C'è un pratico collegamento per un caso d'uso comune. Nel tuo esempio stai facendo:

$ touch file.js
$ openEditor <alt>+<.>

Nel secondo comando, il trucco è scrivere openEditor(con uno spazio dopo) seguito da Alt+ .. Questo inserirà l' ultimo argomento dell'ultimo comando, che èfile.js . (Se non funziona con Altqualche motivo, Escdovrebbe funzionare anche.)

Poiché spesso "oggetto" è effettivamente l'ultimo argomento del comando precedente, questo può essere usato frequentemente. È facile da ricordare e si integrerà rapidamente nel tuo set di scorciatoie shell intuitivamente utilizzate.

Ci sono un sacco di cose che puoi fare con questo, ecco un articolo approfondito sulle possibilità: /programming/4009412/how-to-use-arguments-from-previous-command .

Come bonus questo funzionerà non solo in bash ma in tutti i programmi che usano libreadline per l'elaborazione dell'input da riga di comando.


2
È possibile combinare questo con un argomento cifre , ad esempio, per ottenere la seconda stiva argomento Alte premere 2.(o Esc, 2, Esc, .), per ottenere il secondo per ultimo argomento stampa Alt+ -, il tipo 2e premere Alt+ .(o Esc, -2, Esc, .).
dessert,

@dessert E se corro volessi più di uno degli argomenti? Ad esempio, corro, echo 1 2 3 4poi voglio 2e 3per il prossimo comando
wjandrea,

@dessert L'ho trovato da solo! Devi solo digitare qualcos'altro tra loro, come uno spazio. Per concatenarli, il modo più semplice è digitare uno spazio e quindi backspace.
wjandrea,

1
@wjandrea hold Alte tipo 2., premere la barra spaziatrice, hold Alte tipo 3.- se si desidera un intervallo, l'espansione della cronologia uso: !!:2-3.
dessert,

9

Per quanto riguarda la shell interattiva bashe la shell di script predefinite dash, è possibile utilizzare $_per richiamare l' ultimo argomento dell'ultimo comando .

$ echo "Hello World"; echo same "$_"
Hello World
same Hello World

csh e tcsh hanno riferimenti storici, in particolare per l'ultima parola del comando, è possibile utilizzare !$e per singoli argomenti - !:<index>:

~% echo foo bar
foo bar
~% echo !$
echo bar
bar

% echo bar baz
bar baz
% echo !:1
echo bar
bar

In generale, è semplicemente meglio assegnare qualsiasi cosa sia objectAa una variabile e usarla in più comandi, cicli, ecc. In alternativa, una funzione potrebbe essere una scelta:

$ foo(){ echo "$@"; stat --print="%F\n" "$@";}
$ foo testdir
testdir
directory

1
Vorrei solo sottolineare che $_funziona in modo leggermente diverso rispetto a !#:nquando quest'ultimo viene espanso prima di salvare il comando nella cronologia. Quindi tornare indietro nella storia mostrerebbe ancora il comando con $_mentre !#:nsarebbe stato sostituito con il suo valore reale. Entrambi hanno i loro pro e contro.
Dan,

3
Inoltre, come al solito, $_dovrebbe essere citato, poiché altrimenti viene diviso e mosso come tutto il resto. (Non lo vediamo qui poiché echounisce i suoi argomenti con un unico spazio.) Ad esempio touch "hello there"; ls -l $_ , non funzionerà.
ilkkachu,

1
@Dan Penso che il più grande pro $_sia che sia portatile. Dopotutto, !#:nè specifico per Bash.
Sergiy Kolodyazhnyy il

3

Vorrei sconsigliare l'approccio storico riportato nella risposta di Steeldriver . Questo si basa sullo stato globale, che è sempre fragile.

È meglio eseguire il ciclo in anticipo su tutti i comandi necessari, usando una variabe corretta:

$ for c in touch gedit; do $c foo.txt; done

Il problema in generale è che Bash non si interrompe quando si verifica un errore, ovvero in realtà si comporta come touch foo.txt; gedit foo.txtinvece di incatenarsi &&. Quindi, per sicurezza, puoi aggiungere un break:

$ for c in touch gedit; do $c foo.txt || break; done

1

Quando si cucina un liner, a volte assegno la mia cosa ripetuta a una variabile shell che uso più volte nel comando. Posso richiamarlo e modificarlo per usare un arg diverso con freccia su, controllo + a, controllo + freccia destra per avvicinare il cursore a t=.

t=testloop; asm-link -d "$t.asm" && perf stat -r2 ./"$t"

Si noti che ciò semplifica la virata su un'estensione o una variazione sul nome.

Nota anche che ho bisogno di un ;dopo l'assegnazione della variabile, perché la var=value cmdimposta come variabile d'ambiente per quel comando e non influisce sul contesto della shell.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.