Versteckte Funktionen von Bash


72

Shell-Skripte werden häufig als Klebstoff für die Automatisierung und einfache einmalige Aufgaben verwendet. Was sind einige Ihrer bevorzugten "versteckten" Funktionen der Bash-Shell / Skriptsprache?

  • Eine Funktion pro Antwort
  • Geben Sie ein Beispiel und eine kurze Beschreibung der Funktion, nicht nur einen Link zur Dokumentation
  • Beschriften Sie das Feature mit fettem Titel als erste Zeile

Siehe auch:

Antworten:


69

Fügen Sie den letzten Parameter der vorhergehenden Zeile ein

alt- . die nützlichste Tastenkombination aller Zeiten, probieren Sie es aus und sehen Sie, aus irgendeinem Grund weiß niemand etwas über diese.

Drücken Sie immer wieder darauf, um ältere letzte Parameter auszuwählen.

Großartig, wenn Sie etwas anderes mit etwas machen möchten, das Sie gerade verwendet haben.


Auf jeden Fall +1. Danke für diesen, so nützlich und doch so versteckt.
Alberto Zaccagni

Kann ich Alt + verwenden? um dir +2 zu geben?
Adam Liss

5
Ich bin ein häufiger Benutzer von! $, Aber dies ist weitaus unmittelbarer und nützlicher.
jmanning2k

2
Ich finde es !$zu schwer, schnell zu tippen. Ich muss immer langsamer werden und darüber nachdenken, das Dollarzeichen an zweiter Stelle zu setzen. Alt+ .ist schneller und einfacher. Ganz zu schweigen davon, dass Sie den Text tatsächlich sehen, bevor Sie ihn ausführen.
Dreamlax

Sie können die Parameter auch mit alt + - [0-9] und dann mit alt + umschalten.
Neurolabs

40

Wenn Sie einen Prozess nach dem Abmelden am Laufen halten möchten:

disown -h <pid>

ist eine nützliche integrierte Bash. Im Gegensatz dazu nohupkönnen Sie disowneinen bereits laufenden Prozess ausführen .

Beenden Sie zuerst Ihren Job mit control-Z, rufen Sie die PID ab ps(oder verwenden Sie sie echo $!), bgsenden Sie sie in den Hintergrund und verwenden Sie sie dann disownmit dem Flag -h.

Vergessen Sie nicht, Ihren Job als Hintergrund zu verwenden, da er sonst beim Abmelden beendet wird.


Das ist süß! So oft wollte ich das machen. Können Sie die Ausgaben auch danach umleiten?
Razzed

3
Holen Sie sich besser die PID von jobs -l(oder -p)
Marian

Eh - Ich habe einmal ein C-Programm für im Wesentlichen fork()und exec()seine Argumente geschrieben, im Wesentlichen einen Daemonizer. Ich kann die Granate bombardieren und etwas auf einmal ausführen bgexec google-chrome && exit.
New123456

Hat dies nicht die gleiche Funktionalität von screen?
Kasun Gajasinghe

38

Fast alles, was im Handbuch unter ERWEITERUNG aufgeführt ist

Insbesondere Parametererweiterung:

$ I=foobar
$ echo ${I/oo/aa} #replacement
faabar
$ echo ${I:1:2}   #substring
oo
$ echo ${I%bar}   #trailing substitution
foo
$ echo ${I#foo}   #leading substitution
bar

Schön, so habe ich% Ix = y% in cmd.exe bekommen ... :)
Majkinetor


27

Weitere magische Tastenkombinationen:

  • Ctrl+ rstartet eine "umgekehrte inkrementelle Suche" durch Ihren Befehlsverlauf. Während Sie weiter tippen, wird der neueste Befehl abgerufen, der den gesamten eingegebenen Text enthält.

  • Tab Vervollständigt das Wort, das Sie bisher eingegeben haben, wenn es eindeutig ist.

  • Tab Tab listet alle Vervollständigungen für das Wort auf, das Sie bisher eingegeben haben.

  • Alt+ * fügt alle möglichen Vervollständigungen ein, was besonders hilfreich ist, wenn Sie gerade einen potenziell zerstörerischen Befehl mit Platzhaltern eingegeben haben:

    rm -r source/d*.c Alt + *
    rm -r source/delete_me.c source/do_not_delete_me.c

  • Ctrl+ Alt+ eführt Alias, Verlauf und Shell-Erweiterung in der aktuellen Zeile aus. Mit anderen Worten, die aktuelle Zeile wird erneut angezeigt, da sie von der Shell verarbeitet wird:

    ls $HOME/tmp Ctrl Alt + e
    ls -N --color=tty -T 0 /home/cramey


1
+1 für alt + * (oder alt-shift-8), wodurch Sie den Fehler sehen, den Sie gleich machen werden
Marcus Downing

Ich schaltete alles ein, wenn es nicht eindeutig ist, um nicht zweimal Tab zu treffen.
Chad Gorshing

24

Holen Sie sich Verlaufsbefehle und Argumente zurück

Mit dem !Operator können Sie selektiv auf vorherige Befehle und Argumente zugreifen . Dies ist sehr nützlich, wenn Sie mit langen Pfaden arbeiten.

Sie können Ihre letzten Befehle mit überprüfen history.

Sie können vorherige Befehle verwenden, wobei !<n>dies nder Index des Befehls historyist. Negative Zahlen zählen vom letzten Befehl im Verlauf rückwärts.

ls -l foo bar
touch foo bar
!-2

Sie können vorherige Argumente mit verwenden !:<n>, Null ist der Befehl,> = 1 sind die Argumente.

ls -l foo
touch !:2
cp !:1 bar

Und Sie können beides mit kombinieren !<n>:<m>

touch foo bar
ls -l !:1 !:2
rm !-2:1 !-2:2
!-2

Sie können auch Argumentbereiche verwenden !<n>:<x>-<y>

touch boo far
ls -l !:1-2

Andere !spezielle Modifikatoren sind:

  • * für alle Argumente

    ls -l foo bar
    ls !*
    
  • ^für das erste Argument ( !:1== !^)

  • $ für das letzte Argument

    ls -l foo bar
    cat !$ > /dev/null
    

5
Die ^ R-Tastenkombination ist auch sehr praktisch
Mark Baker

5
Ich mag auch Alt- ^ (Alt-Shift-6 auf US-Tastaturen). Es erweitert Verlaufssequenzen wie !: 2, sodass Sie sehen können, was ein Befehl tun wird, bevor Sie ihn ausführen.
Doug

1
Anstelle von $! Versuchen Sie, ESC + einzugeben. Das letzte Argument wird direkt unter Ihrem Cursor angezeigt.
Philippe A.

20

Ich mag die -x-Funktion, mit der Sie sehen können, was in Ihrem Skript vor sich geht.

bash -x script.sh 

19

SECONDS=0; sleep 5 ; echo "that took approximately $SECONDS seconds"

SEKUNDEN

Jedes Mal, wenn auf diesen Parameter verwiesen wird, wird die Anzahl der Sekunden seit dem Zurückrufen des Shell-Aufrufs angegeben. Wenn SECONDS ein Wert zugewiesen wird, gibt der Wert, der bei nachfolgenden Referenzen zurückgegeben wird, die Anzahl der Sekunden seit der Zuweisung plus den zugewiesenen Wert an. Wenn SECONDS deaktiviert ist, verliert es seine besonderen Eigenschaften, auch wenn es anschließend zurückgesetzt wird.


17

Hier ist einer meiner Favoriten. Dadurch wird festgelegt, dass die Tab-Vervollständigung nicht zwischen Groß- und Kleinschreibung unterscheidet. Es ist wirklich großartig, um schnell Verzeichnispfade einzugeben, insbesondere auf einem Mac, bei dem das Dateisystem standardmäßig nicht zwischen Groß- und Kleinschreibung unterscheidet. Ich habe dies .inputrcin meinem Home-Ordner abgelegt .

set completion-ignore-case on

1
Ich wusste nichts davon, danke. Dies war in meinem ~ / .inputrc bereits gerade auskommentiert. Ich schaltete dies ein und zeigte alles, wenn auch mehrdeutig.
Chad Gorshing

16

Die spezielle Variable zufällig:

if [[ $(($RANDOM % 6)) = 0 ]]
    then echo "BANG"
else
    echo "Try again"
fi   

13
# [$ [$ RANDOM% 6] == 0] && rm -rf / || Echo "Du lebst" :)
Kevin

Keine Notwendigkeit für ein $Siegel innerhalb der arithmetischen Bewertung; Keine separate Bewertung und Prüfung erforderlich: if (( RANDOM % 6 == 0 )); then echo "BANG"; else echo "Try again"; fiOder noch kürzer : (( RANDOM % 6 )) && echo "Try again" || echo "BANG".
Manatwork

13

Umgang mit regulären Ausdrücken

In den letzten Bash-Versionen werden reguläre Ausdrücke abgeglichen, sodass Sie Folgendes tun können:

if [[ "mystring" =~ REGEX ]] ; then  
    echo match
fi

Dabei ist REGEX ein regulärer Rohausdruck in dem von man re_format beschriebenen Format.

Übereinstimmungen von Teilen in Klammern werden im Array BASH_REMATCH gespeichert, beginnend mit Element 1 (Element 0 ist die übereinstimmende Zeichenfolge in ihrer Gesamtheit), sodass Sie dies auch zum Parsen mit Regex verwenden können.


Es fühlt sich irgendwie komisch an, den regulären Ausdruck nicht in Anführungszeichen setzen zu müssen. . .
Dreamlax

13

Ctrlx Ctrle

Dadurch wird der aktuelle Befehl in den in der Variablen VISUAL definierten Editor geladen. Dies ist sehr nützlich für lange Befehle wie einige der hier aufgeführten.

So verwenden Sie vi als Editor:

export VISUAL=vi

set -o vidann geht Esc bei einem Befehl zur Inline-Bearbeitung, ein einfaches 'v' zieht den Befehl in einen vollständigen vi-Editor.
Stephen P

13

Schnelle und fehlerhafte Korrektur von Tippfehlern (besonders nützlich für lange Befehle über langsame Verbindungen, bei denen es schrecklich wäre, den Befehlsverlauf zu verwenden und durch ihn zu scrollen):

$ cat /proc/cupinfo
cat: /proc/cupinfo: No such file or directory
$ ^cup^cpu

Versuchen Sie auch !:s/old/neweinmal, im vorherigen Befehl alt durch neu zu ersetzen.

Wenn Sie viele Vorkommen ersetzen möchten, können Sie eine globale Ersetzung mit durchführen !:gs/old/new.

Sie können die Befehle gsund smit jedem Verlaufsereignis verwenden, z

!-2:s/old/new

Im vorletzten Befehl olddurch new(einmal) ersetzen .


1
Gibt es eine Möglichkeit, mehr über diese oder ähnliche Funktionen zu erfahren? googeln für ^ foo ^ bar ist nicht so befriedigend :)
Tetha

3
Ereignisbezeichner und Modifikatoren in man bash. Versuchen Sie !:s/old/neweinmal, im vorherigen Befehl das Alte durch das Neue zu ersetzen. Wenn Sie viele Vorkommen ersetzen möchten, können Sie eine globale Ersetzung mit durchführen !:gs/old/new. Dies kann mit James 'Post ( stackoverflow.com/questions/211378/hidden-features-of-bash/… ) kombiniert werden , z. B.: ( Ersetzt!$:s/old/new altes durch neues im letzten Argument des vorherigen Befehls), !-2:0:gs/a/s !-2*(ersetzt jedes Vorkommen von a mit s im vorletzten Befehlsnamen und fügt alle Argumente des vorletzten Befehls hinzu). Viel Glück!
Island_jack

10

Hier zwei meiner Favoriten:

Um die Syntax zu überprüfen, ohne das Skript wirklich auszuführen, verwenden Sie:

bash -n script.sh

Gehen Sie zurück zum letzten Verzeichnis (ja, ich kenne Pushd und Popd, aber das geht schneller)

cd -

3
"cd -" hat den Vorteil zu funktionieren, wenn Sie vergessen haben, ein Verzeichnis auf den Stapel zu verschieben, aber trotzdem dorthin zurückkehren möchten.
Temp2290

8

Verwenden von Infool Boolean Operators

Betrachten Sie das einfache wenn:

if [ 2 -lt 3 ]
    then echo "Numbers are still good!"
fi

Das sieht irgendwie hässlich aus. Nicht sehr modern. Wenn Sie doppelte Klammern um Ihren booleschen Ausdruck verwenden, können Sie die normalen booleschen Operatoren verwenden!

if [[ 2 < 3 ]]
    then echo "Numbers are still good!"
fi

3
Dies ist keine Funktion von Bash, sondern ein externes Programm: Ja, '[[' ist ein eigenständiges Programm.
Mathieu Garstecki

2
madmath: Ich denke, Sie werden feststellen, dass [normalerweise ein zu testender Symlink oder Hardlink ist, während [[eine integrierte Shell ist. Es muss von der Shell analysiert werden, sonst <sieht aus wie eine Umleitung der Eingabe.
Greg Hewgill

5
Nein, '[' ist ein eigenständiges Programm. '[[' ist nicht
Vinko Vrsalovic

1
$ type [[[[ist ein Shell-Schlüsselwort $, das [[$ # Keine Ausgabe
Mark A. Nicolosi

Anscheinend mag SO keine Zeilenumbrüche in Kommentaren, hoffentlich ist das nicht zu schwer zu analysieren. Das war auf Ubuntu mit Bash 3.2.39, BTW.
Mark A. Nicolosi

8

Arrays:

#!/bin/bash

array[0]="a string"
array[1]="a string with spaces and \"quotation\" marks in it"
array[2]="a string with spaces, \"quotation marks\" and (parenthesis) in it"

echo "There are ${#array[*]} elements in the array."
for n in "${array[@]}"; do
    echo "element = >>${n}<<"
done

Weitere Details zu Arrays (und anderen erweiterten Bash-Skripten) finden Sie im Advanced Bash-Scripting-Handbuch .


8

Ausführen eines Befehls vor dem Anzeigen der Bash-Eingabeaufforderung

Legen Sie einen Befehl in der env-Variablen "PROMPT_COMMAND" fest, der vor jeder Eingabeaufforderung automatisch ausgeführt wird. Beispiel:

[lsc@home]$ export PROMPT_COMMAND="date"
Fri Jun  5 15:19:18 BST 2009
[lsc@home]$ ls
file_a  file_b  file_c
Fri Jun  5 15:19:19 BST 2009
[lsc@home]$ ls

Fügen Sie für die nächsten April-Narren "export PROMPT_COMMAND = cd" zu .bashrc hinzu, lehnen Sie sich zurück und beobachten Sie, wie sich die Verwirrung entfaltet.


8

Magische Tastenkombinationen von den Bash- manSeiten:

  • Ctrl+ aund Ctrl+ ebewegen den Cursor an den Anfang bzw. das Ende der aktuellen Zeile.

  • Ctrl+ tund Alt+ ttransponieren das Zeichen und das Wort vor dem Cursor mit dem aktuellen und bewegen den Cursor dann vorwärts.

  • Alt+ uund Alt+ lkonvertieren das aktuelle Wort (vom Cursor bis zum Ende) in Groß- und Kleinbuchstaben.

    Tipp: Drücken Sie Alt+ gefolgt von einem dieser Befehle, um den Anfang des aktuellen Wortes zu konvertieren .


Bonus- manTipps:

  • manVerwenden Sie /beim Anzeigen von Seiten die Suche nach Text auf den Seiten. Verwenden Sie ndiese Option, um zum nächsten Spiel oder Nzum vorherigen Spiel zu springen .

  • Beschleunigen Sie die Suche nach einem bestimmten Befehl oder Unterabschnitt innerhalb der manSeiten, indem Sie deren Formatierung nutzen:

    o Anstatt zu tippen /history expansion, um diesen Abschnitt zu finden, versuchen Sie /^history, mit caret ( ^) nur Zeilen zu finden, die mit "history" beginnen .

    o Versuchen Sie /   readmit ein paar führenden Leerzeichen, nach diesem integrierten Befehl zu suchen. Builtins werden immer in die manSeiten eingerückt .


7

export TMOUT=$((15*60))

Beenden Sie die Bash nach 15 Minuten Leerlaufzeit und setzen Sie sie zum Deaktivieren auf 0. Normalerweise lege ich dies auf meinen Root-Konten auf ~ / .bashrc. Dies ist praktisch, wenn Sie Ihre Boxen verwalten, und Sie können vergessen, sich abzumelden, bevor Sie das Terminal verlassen.


7

Rückgängig machen

C-S-- Control Shift Minus Rückgängigmachen von Tippaktionen.

Töte / ziehe

Jeder Löschvorgang C-w(vorheriges Wort löschen), C-k(bis zum Zeilenende löschen), (bis zum Zeilenanfang C-ulöschen) usw. ... kopiert den gelöschten Text in den Tötungsring. Sie können den letzten Tötungsvorgang einfügen mit: C-yund durchlaufen (und) Einfügen aus) dem Ring gelöschter Elemente mitAlt-y


7

Sie können bestimmte Dateien beim Ausfüllen der Registerkarte ignorieren, indem Sie die FIGNOREVariable festlegen .

Wenn Sie beispielsweise ein Subverion-Repo haben und einfacher navigieren möchten, tun Sie dies

export FIGNORE=".svn"

Jetzt können Sie, cdohne von .svnVerzeichnissen blockiert zu werden .


5

Arithmetik verwenden:

if [[ $((2+1)) = $((1+2)) ]]
    then echo "still ok"
fi

Es ist erstaunlich, wie viele Leute das nicht wissen und expr in ihren Skripten verwenden.
Mark Baker

2
Manchmal ist die arithmetische Erweiterung ausreichend: ((2 + 1 == 1 + 2)) && echo OK
Dimitre Radoulov

5

Klammererweiterung

Standarderweiterung mit {x, y, z}:

$ echo foo{bar,baz,blam}
foobar foobaz fooblam
$ cp program.py{,.bak}  # very useful with cp and mv

Sequenzerweiterung mit {x..y}:

$ echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
$ echo {a..f}{0..3}
a0 a1 a2 a3 b0 b1 b2 b3 c0 c1 c2 c3 d0 d1 d2 d3 e0 e1 e2 e3 f0 f1 f2 f3

4

Ich habe kürzlich Csh Programming Considered Harmful gelesen, das dieses erstaunliche Juwel enthielt:

Betrachten Sie die Pipeline:

A | B | C

Sie möchten den Status von C wissen, nun, das ist einfach: Es ist in $? Oder $ status in csh. Aber wenn Sie es von A wollen, haben Sie kein Glück - wenn Sie in der csh sind, ist das. In der Bourne-Shell können Sie es bekommen, obwohl dies etwas schwierig ist. Hier ist etwas, was ich tun musste, wo ich dds stderr in eine grep -v-Pipe lief, um das Ein- / Aus-Rauschen der Datensätze zu beseitigen, aber den Exit-Status des dd zurückgeben musste, nicht den grep's:

device=/dev/rmt8
dd_noise='^[0-9]+\+[0-9]+ records (in|out)$'
exec 3>&1
status=`((dd if=$device ibs=64k 2>&1 1>&3 3>&- 4>&-; echo $? >&4) |
    egrep -v "$dd_noise" 1>&2 3>&- 4>&-) 4>&1`
exit $status;

19
Sie möchten die Variable PIPESTATUS verwenden, die ein Array der Beendigungsstatus jedes Befehls in der Pipe darstellt. $ {PIPESTATUS [0]} wäre das, was Sie hier wollen.
Steve Baker

Steve, das habe ich nie gewusst - poste es als Antwort hier! (Ich werde es positiv bewerten, wenn Sie dies tun :)
Mark Baker

4

Inhalt einer Datei abschneiden (Datei auf Null setzen)

> file

Dies ist insbesondere sehr gut zum Abschneiden von Protokolldateien geeignet, wenn die Datei von einem anderen Prozess geöffnet wird, der möglicherweise noch in die Datei schreibt.


um zu verhindern, dass Sie versehentlich Dateien abschneiden , set -o noclobber. Dann müssen Sie >| fileeine Datei abschneiden.
Glenn Jackman

4

Nicht wirklich eine Funktion , sondern eine Richtung: Ich habe viele „versteckte Features“, Geheimnisse und verschiedene bash Nützlichkeit bei gefunden commandlinefu.com . Viele der am besten bewerteten Antworten auf diese Antworten habe ich auf dieser Seite gelernt :)


4

Noch eine kleine: Alt+#

kommentiert die aktuelle Zeile aus und verschiebt sie in den Verlaufspuffer.

Wenn Sie also eine Befehlszeile zusammenstellen und einen Zwischenbefehl ausgeben müssen, um z. B. eine Datei zu finden, drücken Sie einfach Alt + #, geben den anderen Befehl ein, gehen in den Verlauf, kommentieren aus und fahren fort.


4

Klammern anstelle von dound donein for-Schleife

ForSchleifenkörper sind normalerweise in do...done(nur ein Beispiel):

for f in *;
do
    ls "$f";
done

Aber wir können einen C-Stil mit geschweiften Klammern verwenden:

for f in *; {
    ls "$f";
}

Ich denke das sieht besser aus als do...doneund ich bevorzuge dieses. Ich habe dies noch in keiner Bash-Dokumentation gefunden, daher ist dies wirklich eine versteckte Funktion.


3

Numerische Ausdrücke im C-Stil:

let x="RANDOM%2**8"
echo -n "$x = 0b"
for ((i=8; i>=0; i--)); do
  let n="2**i"
  if (( (x&n) == n )); then echo -n "1"
  else echo -n "0"
  fi
done
echo ""

3

Diese Eigenschaften sind ein weiterer meiner Favoriten.

export HISTCONTROL=erasedups
export HISTSIZE=1000

Der erste stellt sicher, dass bash Befehle nicht mehr als einmal protokolliert, was historydie Nützlichkeit wirklich verbessert . Der andere erweitert die Verlaufsgröße von 100 auf 1000. Ich habe dies auf meinen Computern auf 10000 festgelegt.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.