Hier ist ein Fragment eines zukünftigen Buches, Grundlegende Tools und Praktiken für einen unerfahrenen Softwareentwickler, von Balthazar Ruberol und Etienne Broad . Das Buch soll dazu beitragen, die jüngere Generation von Entwicklern zu erziehen. Es werden Themen wie die Konsole zu meistern, Einrichten und effizient in der Kommando - Shell arbeiten, Versionierung Code mit git
SQL - Grundlagen, Werkzeuge wie Make
, jq
und reguläre Ausdrücke, Grundlagen der Vernetzung sowie Best Practices für die Software - Entwicklung und Zusammenarbeit. Die Autoren arbeiten derzeit intensiv an diesem Projekt und laden alle ein, an der Mailingliste teilzunehmen .Inhalt
Shell-Textverarbeitung
Einer der Gründe, die die Befehlsshell zu einem unschätzbaren Werkzeug machen, ist die große Anzahl von Textverarbeitungsbefehlen und die Möglichkeit, sie einfach in der Pipeline zu kombinieren und komplexe Verarbeitungsvorlagen zu erstellen. Diese Befehle machen viele Aufgaben zum Analysieren von Text und Daten, Konvertieren von Daten zwischen verschiedenen Formaten, Filtern von Zeichenfolgen usw. trivial.Bei der Arbeit mit Textdaten besteht das Hauptprinzip darin, jedes komplexe Problem in viele kleinere zu unterteilen - und jedes zu lösen von ihnen mit einem speziellen Werkzeug.Lassen Sie jedes Programm eines gut machen - Die Grundlagen der Unix-Philosophie
Die Beispiele in diesem Kapitel mögen auf den ersten Blick etwas weit hergeholt erscheinen, aber dies geschieht absichtlich. Jedes der Tools wurde entwickelt, um ein kleines Problem zu lösen. In Kombination werden sie jedoch extrem leistungsfähig.Wir werden uns einige der häufigsten und nützlichsten Textverarbeitungsbefehle in der Befehlsshell ansehen und echte Workflows demonstrieren, die sie miteinander verbinden. Ich schlage vor, das Mana dieser Teams zu betrachten, um die volle Bandbreite der Möglichkeiten zu sehen, die Ihnen zur Verfügung stehen.Eine Beispiel-CSV-Datei ist online verfügbar . Sie können es herunterladen, um das Material zu überprüfen.
Katze
Mit dem Befehl wird cat
eine Liste mit einer oder mehreren Dateien erstellt und deren Inhalt auf dem Bildschirm angezeigt.$ cat Documents/readme
Thanks again for reading this book!
I hope you're following so far!
$ cat Documents/computers
Computers are not intelligent
They're just fast at making dumb things.
$ cat Documents/readme Documents/computers
Thanks again for reading this book!
I hope you are following so far!
Computers are not intelligent
They're just fast at making dumb things.
Kopf
head
druckt die ersten n Zeilen in der Datei. Dies kann sehr nützlich sein, um eine Datei mit unbekannter Struktur und unbekanntem Format zu untersuchen, ohne die gesamte Konsole mit einer Menge Text zu füllen.$ head -n 2 metadata.csv
metric_name,metric_type,interval,unit_name,per_unit_name,description,orientation,integration,short_name
mysql.galera.wsrep_cluster_size,gauge,,node,,The current number of nodes in the Galera cluster.,0,mysql,galera cluster size
Wenn -n
nicht angegeben, werden head
die ersten zehn Zeilen der angegebenen Datei oder des angegebenen Eingabestreams gedruckt.Schwanz
tail
- ein Analogon head
, nur die letzten n Zeilen in der Datei werden angezeigt.$ tail -n 1 metadata.csv
mysql.performance.queries,gauge,,query,second,The rate of queries.,0,mysql,queries
Wenn Sie alle Zeilen drucken möchten, die sich nach der n-ten Zeile befinden (einschließlich dieser), können Sie das Argument verwenden -n +n
.$ tail -n +42 metadata.csv
mysql.replication.slaves_connected,gauge,,,,Number of slaves connected to a replication master.,0,mysql,slaves connected
mysql.performance.queries,gauge,,query,second,The rate of queries.,0,mysql,queries
Unsere Datei enthält 43 Zeilen, daher werden tail -n +42
nur die 42. und 43. Zeile ausgegeben.Wenn der Parameter -n
nicht angegeben wird, tail
werden die letzten zehn Zeilen in der angegebenen Datei oder im angegebenen Eingabestream ausgegeben.tail -f
oder tail --follow
zeigen Sie die letzten Zeilen in der Datei und jede neue Zeile an, während sie in die Datei geschrieben werden. Dies ist sehr nützlich, um Aktivitäten in Echtzeit anzuzeigen, z. B. was in den Webserver-Protokollen aufgezeichnet ist usw.Toilette
wc
(Wortanzahl) zeigt die Anzahl der Zeichen ( -c
), Wörter ( -w
) oder Zeilen ( -l
) in der angegebenen Datei oder dem angegebenen Stream an.$ wc -l metadata.csv
43 metadata.csv
$ wc -w metadata.csv
405 metadata.csv
$ wc -c metadata.csv
5094 metadata.csv
Standardmäßig werden alle oben genannten Elemente angezeigt.$ wc metadata.csv
43 405 5094 metadata.csv
Wenn Textdaten weitergeleitet oder umgeleitet werden, stdin
wird nur der Zähler angezeigt.$ cat metadata.csv | wc
43 405 5094
$ cat metadata.csv | wc -l
43
$ wc -w < metadata.csv
405
grep
grep
- Dies ist ein Schweizer Messer, das Saiten nach einem bestimmten Muster filtert.Zum Beispiel können wir alle Vorkommen des Wortes Mutex in einer Datei finden.$ grep mutex metadata.csv
mysql.innodb.mutex_os_waits,gauge,,event,second,The rate of mutex OS waits.,0,mysql,mutex os waits
mysql.innodb.mutex_spin_rounds,gauge,,event,second,The rate of mutex spin rounds.,0,mysql,mutex spin rounds
mysql.innodb.mutex_spin_waits,gauge,,event,second,The rate of mutex spin waits.,0,mysql,mutex spin waits
grep
kann entweder als Argumente angegebene Dateien oder einen an sie übergebenen Textstrom verarbeiten stdin
. Somit können wir mehrere Befehle verketten grep
, um den Text weiter zu filtern. Im folgenden Beispiel filtern wir die Zeilen in unserer Datei metadata.csv
, um Zeilen zu finden, die sowohl Mutex als auch Betriebssystem enthalten .$ grep mutex metadata.csv | grep OS
mysql.innodb.mutex_os_waits,gauge,,event,second,The rate of mutex OS waits.,0,mysql,mutex os waits
Betrachten wir einige Optionen grep
und ihr Verhalten.grep -v
Führt einen inversen Abgleich durch: Filtert Zeichenfolgen, die nicht mit dem Argumentmuster übereinstimmen.$ grep -v gauge metadata.csv
metric_name,metric_type,interval,unit_name,per_unit_name,description,orientation,integration,short_name
grep -i
Führt einen Matching ohne Berücksichtigung der Groß- und Kleinschreibung durch. Das folgende Beispiel grep -i os
findet sowohl OS und OS .$ grep -i os metadata.csv
mysql.innodb.mutex_os_waits,gauge,,event,second,The rate of mutex OS waits.,0,mysql,mutex os waits
mysql.innodb.os_log_fsyncs,gauge,,write,second,The rate of fsync writes to the log file.,0,mysql,log fsyncs
grep -l
Listet Dateien auf, die eine Übereinstimmung enthalten.$ grep -l mysql metadata.csv
metadata.csv
Das Team grep -c
zählt, wie oft eine Probe gefunden wurde.$ grep -c select metadata.csv
3
grep -r
Sucht rekursiv nach Dateien im aktuellen Arbeitsverzeichnis und allen seinen Unterverzeichnissen.$ grep -r are ~/Documents
/home/br/Documents/computers:Computers are not intelligent
/home/br/Documents/readme:I hope you are following so far!
grep -w
zeigt nur übereinstimmende ganze Wörter.$ grep follow ~/Documents/readme
I hope you are following so far!
$ grep -w follow ~/Documents/readme
$
Schnitt
cut
extrahiert einen Teil der Datei (oder wie üblich den Eingabestream). Der Befehl definiert das Feldtrennzeichen (das die Spalten trennt) mithilfe der Option -d
und die Spaltennummern, die mithilfe der Option abgerufen werden sollen -f
.Mit dem folgenden Befehl wird beispielsweise die erste Spalte aus den letzten fünf Zeilen unserer CSV-Datei abgerufen.$ tail -n 5 metadata.csv | cut -d , -f 1
mysql.performance.user_time
mysql.replication.seconds_behind_master
mysql.replication.slave_running
mysql.replication.slaves_connected
mysql.performance.queries
Da es sich um CSV handelt, werden die Spalten durch ein Komma getrennt, und die Option ist für das Abrufen der ersten Spalte verantwortlich -f 1
.Mit der Option können Sie sowohl die erste als auch die zweite Spalte auswählen -f 1,2
.$ tail -n 5 metadata.csv | cut -d , -f 1,2
mysql.performance.user_time,gauge
mysql.replication.seconds_behind_master,gauge
mysql.replication.slave_running,gauge
mysql.replication.slaves_connected,gauge
mysql.performance.queries,gauge
Einfügen
paste
führt zwei verschiedene Dateien zu einer mehrspaltigen Datei zusammen.$ cat ingredients
eggs
milk
butter
tomatoes
$ cat prices
1$
1.99$
1.50$
2$/kg
$ paste ingredients prices
eggs 1$
milk 1.99$
butter 1.50$
tomatoes 2$/kg
Standardmäßig paste
wird ein Tabulatortrennzeichen verwendet, das jedoch über den Parameter geändert werden kann -d
.$ paste ingredients prices -d:
eggs:1$
milk:1.99$
butter:1.50$
tomatoes:2$/kg
Ein weiterer häufiger Anwendungsfall paste
besteht darin, alle Zeilen in einem Stream oder einer Datei mit dem angegebenen Trennzeichen und einer Kombination aus -s
und zu kombinieren -d
.$ paste -s -d, ingredients
eggs,milk,butter,tomatoes
Wenn ein Parameter als Eingabedatei angegeben -
wird, wird er stattdessen gelesen stdin
.$ cat ingredients | paste -s -d, -
eggs,milk,butter,tomatoes
Sortieren
Der Befehl sort
sortiert die Daten tatsächlich (in der angegebenen Datei oder im angegebenen Eingabestream).$ cat ingredients
eggs
milk
butter
tomatoes
salt
$ sort ingredients
butter
eggs
milk
salt
tomatoes
sort -r
führt eine umgekehrte Sortierung durch.$ sort -r ingredients
tomatoes
salt
milk
eggs
butter
sort -n
Sortiert Felder nach ihrem arithmetischen Wert.$ cat numbers
0
2
1
10
3
$ sort numbers
0
1
10
2
3
$ sort -n numbers
0
1
2
3
10
uniq
uniq
Erkennt und filtert benachbarte identische Zeilen in der angegebenen Datei oder im angegebenen Eingabestream.$ cat duplicates
and one
and one
and two
and one
and two
and one, two, three
$ uniq duplicates
and one
and two
and one
and two
and one, two, three
Da uniq
nur benachbarte Zeilen herausgefiltert werden, verbleiben möglicherweise noch Duplikate in unseren Daten. Um dieselben Zeilen aus einer Datei zu filtern, müssen Sie zuerst deren Inhalt sortieren.$ sort duplicates | uniq
and one
and one, two, three
and two
uniq -c
Am Anfang jeder Zeile wird die Anzahl ihrer Vorkommen eingefügt.$ sort duplicates | uniq -c
3 and one
1 and one, two, three
2 and two
uniq -u
Zeigt nur eindeutige Zeichenfolgen an.$ sort duplicates | uniq -u
and one, two, three
Hinweis. uniq
Dies ist besonders in Kombination mit dem Sortieren nützlich, da Sie mit der Pipeline | sort | uniq
alle doppelten Zeilen in einer Datei oder einem Stream löschen können.
awk
awk
- Dies ist etwas mehr als nur ein Textverarbeitungswerkzeug: Tatsächlich verfügt es über eine ganze Programmiersprache . Was awk
wirklich gut ist, ist das Aufteilen von Dateien in Spalten, und dies mit besonderer Brillanz, wenn Leerzeichen und Tabulatoren in Dateien gemischt werden.$ cat -t multi-columns
John Smith Doctor^ITardis
Sarah-James Smith^I Companion^ILondon
Rose Tyler Companion^ILondon
Hinweis. cat -t
zeigt Registerkarten als an ^I
.
Wie Sie sehen können, sind die Spalten entweder durch Leerzeichen oder Tabulatoren getrennt und nicht immer durch die gleiche Anzahl von Leerzeichen. cut
es ist hier nutzlos, weil es nur mit einem Trennzeichen funktioniert. Es ist awk
jedoch einfach, mit einer solchen Datei umzugehen.awk '{ print $n }'
Zeigt die n-te Spalte im Text an.$ cat multi-columns | awk '{ print $1 }'
John
Sarah-James
Rose
$ cat multi-columns | awk '{ print $3 }'
Doctor
Companion
Companion
$ cat multi-columns | awk '{ print $1,$2 }'
John Smith
Sarah-James Smith
Rose Tyler
Obwohl awk
zu viel mehr fähig, ist die Ausgabe der Lautsprecher wahrscheinlich 99% der Anwendungsfälle in meinem persönlichen Fall.Hinweis. { print $NF }
Zeigt die letzte Spalte in einer Zeile an.
tr
tr
steht für übersetzen . Dieser Befehl ersetzt ein Zeichen durch ein anderes. Es arbeitet entweder mit Zeichen oder Zeichenklassen wie Kleinbuchstaben eingegeben, Leerzeichen, alphanumerische, usw.Auf der Standardeingabe, es tr <char1> <char2>
ersetzt alle Vorkommen von <char1> mit <char2>.$ echo "Computers are fast" | tr a A
computers Are fAst
tr
kann Zeichenklassen mit Notation übersetzen [:class:]
. Eine vollständige Liste der verfügbaren Klassen ist auf der Manpage beschrieben tr
, einige werden hier gezeigt.[:space:]
repräsentiert alle Arten von Leerzeichen, von einfachen Leerzeichen bis zu Tabulatoren oder Zeilenumbrüchen.$ echo "computers are fast" | tr '[:space:]' ','
computers,are,fast,%
Alle Zeichen sind wie Leerzeichen durch Kommas getrennt. Bitte beachten Sie, dass das Zeichen %
am Ende der Ausgabe das Fehlen einer abschließenden neuen Zeile anzeigt. In der Tat wird dieses Zeichen auch in ein Komma umgewandelt.[:lower:]
repräsentiert alle Kleinbuchstaben und [:upper:]
alle Großbuchstaben. Somit wird die Transformation zwischen ihnen trivial.$ echo "computers are fast" | tr '[:lower:]' '[:upper:]'
COMPUTERS ARE FAST
$ echo "COMPUTERS ARE FAST" | tr '[:upper:]' '[:lower:]'
computers are fast
tr -c SET1 SET2
konvertiert alle Zeichen, die nicht in SET1 enthalten sind, in Zeichen in SET2. Im folgenden Beispiel werden alle Zeichen außer den angegebenen Vokalen durch Leerzeichen ersetzt.$ echo "computers are fast" | tr -c '[aeiouy]' ' '
o u e a e a
tr -d
Löscht die angegebenen Zeichen, ersetzt sie jedoch nicht. Dies ist das Äquivalent tr <char> ''
.$ echo "Computers Are Fast" | tr -d '[:lower:]'
C A F
tr
kann auch Zeichenbereiche ersetzen, z. B. alle Buchstaben zwischen a und e oder alle Zahlen zwischen 1 und 8 unter Verwendung der Notation s-e
, wobei s
das Startzeichen und e
das Ende ist.$ echo "computers are fast" | tr 'a-e' 'x'
xomputxrs xrx fxst
$ echo "5uch l337 5p34k" | tr '1-4' 'x'
5uch lxx7 5pxxk
Der Befehl tr -s string1
komprimiert alle mehrfachen Vorkommen von Zeichen string1
in einem einzigen. Eine der nützlichsten Anwendungen tr -s
besteht darin, mehrere aufeinanderfolgende Leerzeichen durch ein Leerzeichen zu ersetzen.$ echo "Computers are fast" | tr -s ' '
Computers are fast
falten
Der Befehl fold
reduziert alle Eingabezeilen auf die angegebene Breite. Beispielsweise kann es hilfreich sein, sicherzustellen, dass der Text auf kleine Displays passt. So fold -w n
stapelt Saiten Breite n Zeichen.$ cat ~/Documents/readme | fold -w 16
Thanks again for
reading this bo
ok!
I hope you're fo
llowing so far!
Der Befehl fold -s
unterbricht Zeilen nur bei Leerzeichen. Es kann mit dem vorherigen kombiniert werden, um die Zeichenfolge auf die angegebene Anzahl von Zeichen zu beschränken.Thanks again
for reading
this book!
I hope you're
following so
far!
sed
sed
Ist ein nicht interaktiver Stream-Editor, mit dem Text im Eingabestream zeilenweise konvertiert wird. Als Eingabe entweder eine Datei oder oder stdin
bei der Ausgabe entweder eine Datei oder stdout
.Editorbefehle können eine oder mehrere Adressen , eine Funktion und Parameter enthalten . Somit sind die Befehle wie folgt:[address[,address]]function[arguments]
Obwohl es sed
viele Funktionen ausführt, werden wir nur das Ersetzen von Text als einen der häufigsten Anwendungsfälle betrachten.Textersetzung
Der Ersetzungsbefehl lautet sed
wie folgt:s/PATTERN/REPLACEMENT/[options]
Beispiel : Ersetzen der ersten Instanz eines Wortes in jeder Zeile einer Datei:$ cat hello
hello hello
hello world!
hi
$ cat hello | sed 's/hello/Hey I just met you/'
Hey I just met you hello
Hey I just met you world
hi
Wir sehen, dass in der ersten Zeile nur die erste Instanz ersetzt wird hello
. Um alle Vorkommen hello
in allen Zeilen zu ersetzen , können Sie die Option g
(bedeutet global ) verwenden.$ cat hello | sed 's/hello/Hey I just met you/g'
Hey I just met you Hey I just met you
Hey I just met you world
hi
sed
Ermöglicht die Verwendung von Trennzeichen außer /
, was insbesondere die Lesbarkeit verbessert, wenn die Befehlsargumente selbst Schrägstriche enthalten.$ cat hello | sed 's@hello@Hey I just met you@g'
Hey I just met you Hey I just met you
Hey I just met you world
hi
Die Adresse teilt dem Editor mit, in welcher Zeile oder in welchem Zeilenbereich die Ersetzung durchgeführt werden soll.$ cat hello | sed '1s/hello/Hey I just met you/g'
Hey I just met you hello
hello world
hi
$ cat hello | sed '2s/hello/Hey I just met you/g'
hello hello
Hey I just met you world
hi
Die Adresse 1
gibt in der ersten Zeile Ersetzen hello
an Hey I just met you
. Wir können den Adressbereich in der Notation angeben <start>,<end>
, wobei es <end>
sich entweder um die Zeilennummer oder $
die letzte Zeile in der Datei handeln kann.$ cat hello | sed '1,2s/hello/Hey I just met you/g'
Hey I just met you Hey I just met you
Hey I just met you world
hi
$ cat hello | sed '2,3s/hello/Hey I just met you/g'
hello hello
Hey I just met you world
hi
$ cat hello | sed '2,$s/hello/Hey I just met you/g'
hello hello
Hey I just met you world
hi
Standardmäßig sed
wird das Ergebnis selbst erstellt stdout
, es kann jedoch auch die Originaldatei mit der Option bearbeitet werden -i
.$ sed -i '' 's/hello/Bonjour/' sed-data
$ cat sed-data
Bonjour hello
Bonjour world
hi
Hinweis. Unter Linux gerade genug -i
. Unter macOS unterscheidet sich das Verhalten des Befehls jedoch geringfügig, sodass -i
Sie ihn direkt danach hinzufügen müssen ''
.
Echte Beispiele
CSV-Filterung mit grep und awk
$ grep -w gauge metadata.csv | awk -F, '{ if ($4 == "query") { print $1, "per", $5 } }'
mysql.performance.com_delete per second
mysql.performance.com_delete_multi per second
mysql.performance.com_insert per second
mysql.performance.com_insert_select per second
mysql.performance.com_replace_select per second
mysql.performance.com_select per second
mysql.performance.com_update per second
mysql.performance.com_update_multi per second
mysql.performance.questions per second
mysql.performance.slow_queries per second
mysql.performance.queries per second
In diesem Beispiel filtert grep
die Datei metadata.csv
zuerst die Zeilen, die das Wort enthalten gauge
, dann die Zeilen mit der query
vierten Spalte und zeigt den Metriknamen (1. Spalte) mit dem entsprechenden Wert per_unit_name
(5. Spalte) an.Zeigt die IPv4-Adresse an, die der Netzwerkschnittstelle zugeordnet ist
$ ifconfig en0 | grep inet | grep -v inet6 | awk '{ print $2 }'
192.168.0.38
Der Befehl ifconfig <interface name>
zeigt Informationen zur angegebenen Netzwerkschnittstelle an. Zum Beispiel:en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
ether 19:64:92:de:20:ba
inet6 fe80::8a3:a1cb:56ae:7c7c%en0 prefixlen 64 secured scopeid 0x7
inet 192.168.0.38 netmask 0xffffff00 broadcast 192.168.0.255
nd6 options=201<PERFORMNUD,DAD>
media: autoselect
status: active
Dann laufen Sie grep
für inet
, das ergibt zwei Korrespondenzzeilen.$ ifconfig en0 | grep inet
inet6 fe80::8a3:a1cb:56ae:7c7c%en0 prefixlen 64 secured scopeid 0x7
inet 192.168.0.38 netmask 0xffffff00 broadcast 192.168.0.255
Verwenden Sie dann grep -v
Ausschließen der Zeile mit ipv6
.$ ifconfig en0 | grep inet | grep -v inet6
inet 192.168.0.38 netmask 0xffffff00 broadcast 192.168.0.255
Schließlich awk
fordern wir mit Hilfe die zweite Spalte in dieser Zeile an: Dies ist die IPv4-Adresse, die unserer Netzwerkschnittstelle zugeordnet ist en0
.$ ifconfig en0 | grep inet | grep -v inet6 | awk '{ print $2 }'
192.168.0.38
Hinweis. Mir wurde angeboten , durch grep inet | grep -v inet6
ein so zuverlässiges Team zu ersetzen awk
:
$ ifconfig en0 | awk ' $1 == "inet" { print $2 }'
192.168.0.38
Es ist kürzer und speziell auf IPv4 mit der Bedingung ausgerichtet $1 == "inet"
.
Abrufen eines Werts aus einer Konfigurationsdatei
$ grep 'editor =' ~/.gitconfig | cut -d = -f2 | sed 's/ //g'
/usr/bin/vim
Suchen Sie in der Git-Konfigurationsdatei des aktuellen Benutzers nach dem Wert editor =
, schneiden Sie das Zeichen zu =
, extrahieren Sie die zweite Spalte und löschen Sie alle Leerzeichen.$ grep 'editor =' ~/.gitconfig
editor = /usr/bin/vim
$ grep 'editor =' ~/.gitconfig | cut -d'=' -f2
/usr/bin/vim
$ grep 'editor =' ~/.gitconfig | cut -d'=' -f2 | sed 's/ //'
/usr/bin/vim
Extrahieren Sie IPs aus einer Protokolldatei
Der folgende echte Code sucht im Datenbankprotokoll nach einer Nachricht Too many connections from
(gefolgt von einer IP-Adresse) und zeigt die zehn wichtigsten Eindringlinge an.$ grep 'Too many connections from' db.log | \
awk '{ print $12 }' | \
sed 's@/@@' | \
sort | \
uniq -c | \
sort -rn | \
head -n 10 | \
awk '{ print $2 }'
10.11.112.108
10.11.111.70
10.11.97.57
10.11.109.72
10.11.116.156
10.11.100.221
10.11.96.242
10.11.81.68
10.11.99.112
10.11.107.120
Mal sehen, was diese Pipeline macht. Wie sieht die Zeile im Protokoll aus?$ grep "Too many connections from" db.log | head -n 1
2020-01-01 08:02:37,617 [myid:1] - WARN [NIOServerCxn.Factory:1.2.3.4/1.2.3.4:2181:NIOServerCnxnFactory@193] - Too many connections from /10.11.112.108 - max is 60
Anschließend wird awk '{ print $12 }'
die IP-Adresse aus der Zeichenfolge extrahiert.$ grep "Too many connections from" db.log | awk '{ print $12 }'
/10.11.112.108
...
Der Befehl sed 's@/@@'
löscht den anfänglichen Schrägstrich.$ grep "Too many connections from" db.log | awk '{ print $12 }' | sed 's@/@@'
10.11.112.108
...
Hinweis. Wie wir bereits gesehen haben, können sed
Sie in jedem Trennzeichen verwenden. Obwohl es normalerweise als Trennzeichen verwendet wird /
, ersetzen wir hier dieses spezielle Zeichen, was die Lesbarkeit des Substitutionsausdrucks geringfügig beeinträchtigt.
sed 's/\///'
sort | uniq -c
sortiert IP-Adressen in lexikografischer Reihenfolge und entfernt dann Duplikate, wobei die Anzahl der Einträge vor jeder IP-Adresse hinzugefügt wird.$ grep 'Too many connections from' db.log | \
awk '{ print $12 }' | \
sed 's@/@@' | \
sort | \
uniq -c
1379 10.11.100.221
1213 10.11.103.168
1138 10.11.105.177
946 10.11.106.213
1211 10.11.106.4
1326 10.11.107.120
...
sort -rn | head -n 10
sortiert die Zeilen nach der Anzahl der Vorkommen, numerisch und in umgekehrter Reihenfolge, sodass zuerst die Hauptverletzer angezeigt werden, von denen 10 Zeilen angezeigt werden. Der letzte Befehl awk { print $2 }
ruft die IP-Adressen selbst ab.$ grep 'Too many connections from' db.log | \
awk '{ print $12 }' | \
sed 's@/@@' | \
sort | \
uniq -c | \
sort -rn | \
head -n 10 | \
awk '{ print $2 }'
10.11.112.108
10.11.111.70
10.11.97.57
10.11.109.72
10.11.116.156
10.11.100.221
10.11.96.242
10.11.81.68
10.11.99.112
10.11.107.120
Umbenennen einer Funktion in der Quelldatei
Stellen Sie sich vor, wir arbeiten an einem Projekt und möchten die unterbenannte Funktion (oder Klasse, Variable usw.) in der Quelldatei umbenennen. Sie können dies mit einem Befehl tun sed -i
, der direkt in der Originaldatei ersetzt wird.$ cat izk/utils.py
def bool_from_str(s):
if s.isdigit():
return int(s) == 1
return s.lower() in ['yes', 'true', 'y']
$ sed -i 's/def bool_from_str/def is_affirmative/' izk/utils.py
$ cat izk/utils.py
def is_affirmative(s):
if s.isdigit():
return int(s) == 1
return s.lower() in ['yes', 'true', 'y']
Hinweis. sed -i
Verwenden Sie stattdessen unter macOS sed -i ''
.
Wir haben die Funktion jedoch nur in der Originaldatei umbenannt. Dadurch wird der Import bool_from_str
in eine andere Datei unterbrochen, da diese Funktion nicht mehr definiert ist. Wir müssen einen Weg finden, um bool_from_str
während unseres Projekts umzubenennen . Dies kann erreicht werden unter Verwendung von Befehlen grep
, sed
sowie Schleifen for
oder Verwendung xargs
.Vertiefung: Zyklen for
undxargs
Um alle Vorkommen in unserem Projekt zu ersetzen bool_from_str
, müssen Sie sie zuerst rekursiv mit finden grep -r
.$ grep -r bool_from_str .
./tests/test_utils.py:from izk.utils import bool_from_str
./tests/test_utils.py:def test_bool_from_str(s, expected):
./tests/test_utils.py: assert bool_from_str(s) == expected
./izk/utils.py:def bool_from_str(s):
./izk/prompt.py:from .utils import bool_from_str
./izk/prompt.py: default = bool_from_str(os.environ[envvar])
Da wir nur an Dateien mit Übereinstimmungen interessiert sind, müssen Sie auch die Option verwenden -l/--files-with-matches
:-l, --files-with-matches
Only the names of files containing selected lines are written to standard out-
put. grep will only search a file until a match has been found, making
searches potentially less expensive. Pathnames are listed once per file
searched. If the standard input is searched, the string ``(standard input)''
is written.
$ grep -r --files-with-matches bool_from_str .
./tests/test_utils.py
./izk/utils.py
./izk/prompt.py
Dann können wir den Befehl verwenden xargs
, um Aktionen aus jeder Zeile der Ausgabe auszuführen (dh aus allen Dateien, die die Zeile enthalten bool_from_str
).$ grep -r --files-with-matches bool_from_str . | \
xargs -n 1 sed -i 's/bool_from_str/is_affirmative/'
Die Option -n 1
gibt an, dass jede Zeile in der Ausgabe einen separaten Befehl ausführen soll sed
.Dann werden die folgenden Befehle ausgeführt:$ sed -i 's/bool_from_str/is_affirmative/' ./tests/test_utils.py
$ sed -i 's/bool_from_str/is_affirmative/' ./izk/utils.py
$ sed -i 's/bool_from_str/is_affirmative/' ./izk/prompt.py
Wenn der Befehl, mit dem Sie xargs
(in unserem Fall sed
) aufrufen, mehrere Argumente unterstützt, sollten Sie das Argument -n 1
für die Leistung verwerfen .grep -r --files-with-matches bool_from_str . | xargs sed -i 's/bool_from_str/is_affirmative/'
Dieser Befehl wird dann ausgeführt$ sed -i 's/bool_from_str/is_affirmative/' ./tests/test_utils.py ./izk/utils.py ./izk/prompt.py
Hinweis. Aus der Zusammenfassung sed
auf der Manpage geht hervor, dass das Team mehrere Argumente annehmen kann.
SYNOPSIS
sed [-Ealn] command [file ...]
sed [-Ealn] [-e command] [-f command_file] [-i extension] [file ...]
Wie wir im vorherigen Kapitel gesehen haben, file ...
bedeutet dies, dass mehrere Argumente akzeptiert werden, bei denen es sich um Dateinamen handelt.
Wir sehen, dass für alle Vorkommen Ersetzungen vorgenommen werden bool_from_str
.$ grep -r is_affirmative .
./tests/test_utils.py:from izk.utils import is_affirmative
./tests/test_utils.py:def test_is_affirmative(s, expected):
./tests/test_utils.py: assert is_affirmative(s) == expected
./izk/utils.py:def is_affirmative(s):
./izk/prompt.py:from .utils import is_affirmative
./izk/prompt.py: default = is_affirmative(os.environ[envvar])
Wie so oft gibt es verschiedene Möglichkeiten, um das gleiche Ergebnis zu erzielen. Stattdessen xargs
könnten wir Schleifen verwenden for
, um über die Zeilen in der Liste zu iterieren und für jedes Element Maßnahmen zu ergreifen. Diese Schleifen haben die folgende Syntax:for item in list; do
command $item
done
Wenn wir uns Befehl wickeln grep
in $()
, dann wird die Schale in einem ausführen Subshell , wobei das Ergebnis davon wird dann in einer Schleife wiederholt werden for
.$ for file in $(grep -r --files-with-matches bool_from_str .); do
sed -i 's/bool_from_str/is_affirmative/' $file
done
Dieser Befehl wird ausgeführt$ sed -i 's/bool_from_str/is_affirmative/' ./tests/test_utils.py
$ sed -i 's/bool_from_str/is_affirmative/' ./izk/utils.py
$ sed -i 's/bool_from_str/is_affirmative/' ./izk/prompt.py
Die Schleifensyntax for
scheint mir klarer zu sein xargs
, aber letztere kann Befehle parallel mithilfe von Parametern ausführen -P n
, wobei n
die maximale Anzahl parallel ausgeführter Befehle gleichzeitig ausgeführt wird, was zu einem Leistungsgewinn führen kann.Zusammenfassung
All diese Tools eröffnen eine ganze Welt von Möglichkeiten, da Sie damit Daten extrahieren und transformieren können und ganze Pipelines von Teams erstellen können, die möglicherweise nie zusammenarbeiten wollten. Jeder von ihnen führt eine relativ kleine Funktion aus (Sortieren sort
, Kombinieren cat
, Filtern grep
, Bearbeiten sed
, Schneiden cut
usw.).Jede Aufgabe, die Text enthält, kann auf eine Pipeline kleinerer Aufgaben reduziert werden, von denen jede eine einfache Aktion ausführt und ihre Ausgabe an die nächste Aufgabe überträgt.Wenn wir beispielsweise wissen möchten, wie viele eindeutige IP-Adressen in der Protokolldatei enthalten sind und diese IP-Adressen immer in derselben Spalte angezeigt werden, können wir die folgende Befehlsfolge ausführen:grep
Zeichenfolgen, die dem Muster von Zeichenfolgen mit IP-Adressen entsprechen
- Suchen Sie die Spalte mit der IP-Adresse und extrahieren Sie sie mit
awk
- Sortieren Sie die Liste der IP-Adressen mit
sort
- benachbarte Duplikate mit entfernen
uniq
- Zählen Sie die Anzahl der Zeilen (d. h. eindeutige IP-Adressen) mit
wc -l
Da es viele native Textverarbeitungswerkzeuge von Drittanbietern gibt, gibt es auch viele Möglichkeiten, Probleme zu lösen.Die Beispiele in diesem Artikel waren weit hergeholt, aber ich schlage vor, Sie lesen den erstaunlichen Artikel „Befehlszeilentools können 235-mal schneller sein als Ihr Hadoop-Cluster“ , um eine Vorstellung davon zu bekommen, wie nützlich und leistungsfähig diese Befehle wirklich sind und welche wirklichen Probleme auftreten sie können entscheiden.Was weiter
- Zählen Sie die Anzahl der Dateien und Verzeichnisse in Ihrem Home-Verzeichnis.
- .
- , .
- . .
« » (Essential Tools and Practices for the Aspiring Software Developer) , . , , , , git
, SQL, Make
, jq
, , .
, !