Textdateien mit regulären Ausdrücken durchsuchen

Solcherlei Ausdrücke stellen eine Art Filtersprache für Textdateien dar.

In der ins Deutsche übersetzten man-Page von grep unter https://man.archlinux.org/man/grep.1.de lesen wir zur Einführung folgendes:

Grundlegende Bausteine sind die regulären Ausdrücke, die auf ein einzelnes Zeichen passen.
Die meisten Zeichen, insbesondere alle Buchstaben und Ziffern, sind zugleich reguläre Ausdrücke,
die auf sich selbst passen.
Alle Metazeichen, die eine besondere Bedeutung besitzen, können durch einen vorangestellten
Rückschrägstrich geschützt werden.

Der Punkt . steht für jedes einzelne Zeichen. Es ist nicht festgelegt, ob er auf einen
Kodierfehler passt.

Mit dem genannten einzelnen Punkt haben wir also schon einen speziellen Regex kennengelernt, der als eine Art Platzhalter für EIN beliebiges Zeichen steht.

Zur Motiavtion: Die Stabilität von Linux kommt auch von geringem Programmierballast:

tux@debian11 ~$ file /etc/*.conf | head
/etc/adduser.conf:      ASCII text
/etc/debconf.conf:      ASCII text
/etc/deluser.conf:      ASCII text
/etc/e2scrub.conf:      ASCII text
/etc/gai.conf:          ASCII text
/etc/host.conf:         ASCII text
/etc/ld.so.conf:        ASCII text
/etc/libaudit.conf:     ASCII text
/etc/mke2fs.conf:       ASCII text
/etc/nsswitch.conf:     ASCII text
tux@debian11 ~$
tux@debian11 ~$ #  >> Ziel: Filter schreiben.
tux@debian11 ~$
tux@debian11 ~$ wc -l /etc/adduser.conf
85 /etc/adduser.conf
tux@debian11 ~$
tux@debian11 ~$ grep -v '^#' /etc/adduser.conf | wc -l
38
tux@debian11 ~$
tux@debian11 ~$ grep -v '^#\|^$' /etc/adduser.conf | wc -l
19
tux@debian11 ~$
tux@debian11 ~$ #   >> es sind gar nur 19 aktivierte Zeilen   :-)

Einfache Ausdrücke mit Ankern

  1. Zeilenanfang: ^

  2. Zeilenende: $

  3. Wortanfang: \<

  4. Wortende: \>

Fangen wir mit einer einfachen Textdatei an:

tux@debian11 ~$ # Wir erstellen eine neue Datei und geben ihr den nachfolgenden Inhalt:
tux@debian11 ~$ vi ankertest.txt
tux@debian11 ~$ cat ankertest.txt
Am Anfang war das O.
Wieso?
Am Anfang war das Z.
Komplett
verkehrte Welt
Ohne Geld
und ohne Gut
Ich zieh' den Hut
Am Anfang war W
Wildnis ist ok
Alpha und Agemo.
Aaron an der Aare in Aargau
Aaaah - wie wunderbar
So so!
tux@debian11 ~$
tux@debian11 ~$
## Am Zeilenende muss ein kleines t stehen:
tux@debian11 ~$ grep --color 't$' ankertest.txt
Komplett
verkehrte welt
und ohne Gut
Ich zieh' den Hut
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ grep welt ankertest.txt
verkehrte welt
tux@debian11 ~$
tux@debian11 ~$ ## Die Zeichenkette "Anfang" als Wort finden:
tux@debian11 ~$ grep --color '\<Anfang\>' ankertest.txt
Am Anfang war das O.
Am Anfang war das Z.
Am Anfang war W
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ # An dieser Stelle sind 3 Optionen sinnvoll einsetzbar:
tux@debian11 ~$ grep --color -c '\<Anfang\>' ankertest.txt
3
tux@debian11 ~$
tux@debian11 ~$ grep --color -n '\<Anfang\>' ankertest.txt
1:Am Anfang war das O.
3:Am Anfang war das Z.
9:Am Anfang war W
tux@debian11 ~$ #     >> (c)ount und (n)umbering ist sehr nett
tux@debian11 ~$

tux@debian11 ~$ # Die dritte Option ist:  -o, --only-matching
tux@debian11 ~$ grep --color -o '\<Anfang\>' ankertest.txt
Anfang
Anfang
Anfang
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ ## Außerdem wichtig:   -v, --invert-match
tux@debian11 ~$ grep --color -v '\<Anfang\>' ankertest.txt
Wieso?
Komplett
verkehrte Welt
Ohne Geld
und ohne Gut
Ich zieh' den Hut
Wildnis ist ok
Alpha und Agemo.
Aaron an der Aare in Aargau
Aaaah - wie wunderbar
So so!
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ ## Anstelle von '-v' das Metazeichen für Negation verwenden:   [^...]
tux@debian11 ~$ grep --color '^[^K]' ankertest.txt
Am Anfang war das O.
Wieso?
Am Anfang war das Z.
verkehrte Welt
Ohne Geld
und ohne Gut
Ich zieh' den Hut
Am Anfang war W
Wildnis ist ok
Alpha und Agemo.
Aaron an der Aare in Aargau
Aaaah - wie wunderbar
So so!
tux@debian11 ~$ # Was jetzt fehlt, ist diese Zeile:
tux@debian11 ~$ grep '^[K]' ankertest.txt
Komplett
tux@debian11 ~$

Mittels Here-Doc eine neue Textdatei erstellen:

tux@debian11 ~$ cat > myscript.sh <<\EOF
> # Datum ausgeben:
> date
>
> # Arbeitsverzeichnis ausgeben:
> echo $PWD
>
> # Kalender ausgeben:
> ncal
> EOF
tux@debian11 ~$
tux@debian11 ~$ vi myscript.sh
tux@debian11 ~$ cat myscript.sh
# Datum ausgeben:
date

# Arbeitsverzeichnis ausgeben:
echo $PWD

# Kalender ausgeben:
ncal

# Ich bin root
whoami
tux@debian11 ~$
tux@debian11 ~$ grep '^d' myscript.sh
date
tux@debian11 ~$
tux@debian11 ~$ grep 'd' myscript.sh
date
# Kalender ausgeben:
tux@debian11 ~$
tux@debian11 ~$ grep --color 'd' myscript.sh
date
# Kalender ausgeben:
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ grep --color 'e' myscript.sh
# Datum ausgeben:
date
# Arbeitsverzeichnis ausgeben:
echo $PWD
# Kalender ausgeben:
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ grep --color 'ec' myscript.sh
echo $PWD
tux@debian11 ~$ #    >> Letzteres ist eine Musterübereinstimmung (2 Zeichen in dieser Reihenfolge: "ec")

Wir beschäftigen uns weiter mit Textankern:

tux@debian11 ~$ grep --color 'e$' myscript.sh
date
tux@debian11 ~$
tux@debian11 ~$ #   >> Zeile muss mit einem 'e' enden.
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ grep --color '\<aus' myscript.sh
# Datum ausgeben:
# Arbeitsverzeichnis ausgeben:
# Kalender ausgeben:
tux@debian11 ~$
tux@debian11 ~$ grep --color '\<aus\>' myscript.sh
tux@debian11 ~$
tux@debian11 ~$ #   >> kein Treffer, weshalb wir eine passende Zeile hinzufügen...
tux@debian11 ~$
tux@debian11 ~$ echo '# Dies stammt aus der Unix-Urzeit.' >> myscript.sh
tux@debian11 ~$
tux@debian11 ~$ grep --color '\<aus\>' myscript.sh
# Dies stammt aus der Unix-Urzeit.
tux@debian11 ~$ #   >> das gibt nun eine Übereinstimmung
tux@debian11 ~$
tux@debian11 ~$ wc -l myscript.sh
15 myscript.sh
tux@debian11 ~$
tux@debian11 ~$ # Zur Erzeugung einer Leerzeiele mittels 'echo' benötigen wir '\n':
tux@debian11 ~$ echo -en '\n' >> myscript.sh
tux@debian11 ~$
tux@debian11 ~$ wc -l myscript.sh
16 myscript.sh
tux@debian11 ~$
tux@debian11 ~$ cat -n myscript.sh | tail -5
    12
    13
    14
    15      # Dies stammt aus der Unix-Urzeit.
    16
tux@debian11 ~$
tux@debian11 ~$ grep '^$' myscript.sh
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ grep -v '^$' myscript.sh
# Datum ausgeben:
date
# Arbeitsverzeichnis ausgeben:
echo $PWD
# Kalender ausgeben:
ncal
# Ich bin root
whoami
# Dies stammt aus der Unix-Urzeit.
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ grep --help | grep '\-v'
-v, --invert-match        select non-matching lines
-V, --version             display version information and exit
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$

tux@debian11 ~$
tux@debian11 ~$ # Oder besser:
tux@debian11 ~$ grep --invert-match '^$' myscript.sh
# Datum ausgeben:
date
# Arbeitsverzeichnis ausgeben:
echo $PWD
# Kalender ausgeben:
ncal
# Ich bin root
whoami
# Dies stammt aus der Unix-Urzeit.
tux@debian11 ~$

Quantifier = Wiederholung des zuvor notierten Zeichens

In man grep sind die Zeichen und ihre Bedeutung wie folgt beschrieben:

Repetition

A regular expression may be followed by one of several repetition operators:
?      The preceding item is optional and matched at most once.
*      The preceding item will be matched zero or more times.
+      The preceding item will be matched one or more times.
{n}    The preceding item is matched exactly n times.
{n,}   The preceding item is matched n or more times.
{,m}   The preceding item is matched at most m times.  This is a GNU extension.
{n,m}  The preceding item is matched at least n times, but not more than m times.

Wir beginnen mit dem Stern. Ziel ist, nur Zeilen zu finden, die mindestens zwei aufeinanderfolgende „aa“ aufweisen:

tux@debian11 ~$ grep -i 'aaa*' ankertest.txt
Aaron an der Aare in Aargau
Aaaah - wie wunderbar
tux@debian11 ~$

Wir brauchen oft ein Verhalten, wie es der Dateijoker Stern (‚*‘) ermöglicht, der eine Übereinstimmung mit einer beliebig langen Zeichenkette beliebiger Zeichen (auch kein Zeichen) ermöglicht. Bei den regulären Ausdrücken übernehmen das zwei Zeichen in Kombination, nämlich:

  • Punkt = EIN beliebiges Zeichen

  • Stern = Das davor stehende Zeichen beliebig oft, auch kein mal

Siehe dazu dies:

tux@debian11 ~$ grep  '^e.*D$' myscript.sh
echo $PWD
ezD
tux@debian11 ~$
tux@debian11 ~$ grep  '^eD$' myscript.sh
tux@debian11 ~$
tux@debian11 ~$ echo 'eD' >> myscript.sh
tux@debian11 ~$
tux@debian11 ~$ grep  '^eD$' myscript.sh
eD
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ grep  '^e*D$' myscript.sh
eD
tux@debian11 ~$
tux@debian11 ~$ grep -E '^e*D$' myscript.sh
eD
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ echo 'eeeeD' >> myscript.sh
tux@debian11 ~$ grep -E '^e*D$' myscript.sh
eD
eeeeD
tux@debian11 ~$
tux@debian11 ~$ grep -E '^e.*D$' myscript.sh
echo $PWD
ezD
eD
eeeeD
tux@debian11 ~$

ACHTUNG: Wenn wir den Quantifier ? mit einfachem grep realisieren wollen, brauchen wir \?, was hier KEINE Maskierung bedeutet (kein Literal!). Aus man grep:

Basic vs Extended Regular Expressions

In basic regular expressions the meta-characters ?, +, {, |, (, and )  lose  their  special  meaning;
instead use the backslashed versions \?, \+, \{, \|, \(, and \).

Ein praktischer Ausdruck, der keine Kommentarzeilen und auch keine Leerzeilen ausgibt:

tux@debian11 ~$ grep -v '^#\|^$' myscript.sh
date
echo $PWD
ncal
whoami
ezD
eD
eeeeD
tux@debian11 ~$
tux@debian11 ~$ grep -Ev '^#|^$' myscript.sh
date
echo $PWD
ncal
whoami
ezD
eD
eeeeD
tux@debian11 ~$
tux@debian11 ~$ #   >> Im Falle von 'egrep' oder 'grep -E'.

TIPP: Wenn Kommentarzeilen unglücklicherweise mit führenden Leerzeichen eingerückt wurden, hilft grep -Ev '^\s*#|^$' myConfig, um wirklich nur die aktivierten Zeilen auszugeben.

Nun wollen wir mit dem Fragezeichen arbeiten, wobei der ssh-Server ist auf diesem System noch nicht installiert ist:

tux@debian11 ~$ find /etc -type f -name "*conf*" | grep --color 'sshd'
tux@debian11 ~$
tux@debian11 ~$ # Was es aber natürlich gibt, ist die ssh-Clientkonfigurationsdatei:
tux@debian11 ~$ find /etc -type f -name "*conf*" | grep --color 'ssh'
/etc/ssh/ssh_config
tux@debian11 ~$ #    >> ohne '?' ist ein exaktes Muster erforderlich

Um die Funktionsweise von ‚?‘ zu erkunden, stellen wir schon mal ein ‚d‘ voran, was dann später die Konfigurationsdatei des noch zu installierenden SSH-Daemons finden wird. Momentan passt es aber nur auf ‚ssh_config‘:

tux@debian11 ~$ find /etc -type f -name "*conf*" | grep --color 'sshd\?'
/etc/ssh/ssh_config
tux@debian11 ~$ #   >> erstmal nur eine Datei zu finden
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ apt -y install openssh-server > /dev/null 2>&1 ; echo $?
0
tux@debian11 ~$
tux@debian11 ~$ find /etc -type f -name "*conf*" | grep --color 'sshd\?'
/etc/ssh/sshd_config
/etc/ssh/ssh_config
tux@debian11 ~$
tux@debian11 ~$ #  >> siehe da, ...   :-)
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ # Mit ERE:
tux@debian11 ~$ find /etc -type f -name "*conf*" | grep -E --color 'sshd?'
/etc/ssh/sshd_config
/etc/ssh/ssh_config
tux@debian11 ~$

Quantifier anhand einer weiteren Datei

Wir erzeugen eine neue Datei, die aus mehreren Zeilen besteht:

tux@debian11 ~$ printf 'Wort\nWort1\nWort0815\nWort47\nWort6279\n' > words.txt
tux@debian11 ~$
tux@debian11 ~$ cat words.txt
Wort
Wort1
Wort0815
Wort47
Wort6279
tux@debian11 ~$
tux@debian11 ~$

tux@debian11 ~$
tux@debian11 ~$ nl words.txt
    1       Wort
    2       Wort1
    3       Wort0815
    4       Wort47
    5       Wort6279
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep --color 'Wort[1-9]*\>'
Wort
Wort1
Wort47
Wort6279
tux@debian11 ~$
tux@debian11 ~$ #  >> alles außer die Zeile mit 0815, weil die Null nicht in der Zeichenklasse '[1-9]'
tux@debian11 ~$ #  enthalten ist.
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep 'Wort[1-9]\?\>'
Wort
Wort1
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep -E 'Wort[1-9]?\>'
Wort
Wort1
tux@debian11 ~$
tux@debian11 ~$ #    >> Entweder '\?' (BRE) oder '?' (ERE) verwenden!
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ #    Das Fragezeichen bedeutet: Das eine Zeichen aus dem Bereich der Ziffern 123456789
tux@debian11 ~$ #    ausgeben, wobei dies optional ist, "Wort" also auch gefunden wird.
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep -E 'Wort[[:alnum:]]?\>'
Wort
Wort1
tux@debian11 ~$ #     >> ist dasselbe
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ ## Der Wiederholer '*':
tux@debian11 ~$ cat words.txt | grep --color 'Wort[1-9]*'
Wort
Wort1
Wort0815
Wort47
Wort6279
tux@debian11 ~$
tux@debian11 ~$ #   >> Wieder fast alles (keine Null in der Klasse)
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep -E --color 'Wort[1-9]*'
Wort
Wort1
Wort0815
Wort47
Wort6279
tux@debian11 ~$
tux@debian11 ~$ #   >> egrep macht es genauso.
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep -E --color 'Wort[0-9][0-9]*'
Wort1
Wort0815
Wort47
Wort6279
tux@debian11 ~$ #   >> Zeile 1 ("Wort") fehlt jetzt, weil die erste Ziffer (= 5. Zeichen) auftreten MUSS,
tux@debian11 ~$ #   das 6. Zeichen aber als Ziffer auftreten KANN.

Vom Stern zum Plus

Anstelle eines weiteren Ausdrucks [0-9]* wollen wir nun das Plus einsetzen, was die Sache vereinfacht. So lässt sich nun mit [0-9]+ nach beliebig langen Ziffernfolgen suchen. Anders ausgedrückt, muss hier mindestens eine Ziffer vorkommen:

tux@debian11 ~$ # Die alte Methode mit dem Stern:
tux@debian11 ~$ cat words.txt | grep -E --color 'Wort[0-9][0-9]*'
Wort1
Wort0815
Wort47
Wort6279
tux@debian11 ~$
tux@debian11 ~$ # Die bessere Methode mit dem Plus:
tux@debian11 ~$ cat words.txt | grep -E --color 'Wort[0-9]+'
Wort1
Wort0815
Wort47
Wort6279
tux@debian11 ~$
tux@debian11 ~$ #   >> Das Ergebnis ist dasselbe ("Wort" kommt nicht vor), es bedeutet, dass
tux@debian11 ~$ #   das vorangestellte Zeichen mindestens EIN mal auftreten muss!

Übertragen wir das Ganze nun auf 2 fixe Ziffern:

tux@debian11 ~$ cat words.txt | grep -E  'Wort[0-9][0-9][0-9]*'
Wort0815
Wort47
Wort6279
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep -E  'Wort[0-9][0-9]+'
Wort0815
Wort47
Wort6279
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep -E  'Wort[9876543210]+'
Wort1
Wort0815
Wort47
Wort6279
tux@debian11 ~$

Es folgen weitere Beispiele, die demonstrieren sollen, dass der Inhalt zwischen den eckigen Klammern nicht in üblicher Reihenfolge stehen muss. Außerdem wollen wir eine explizite Zeichenkettelänge haben:

tux@debian11 ~$ cat words.txt | grep -E  'Wort[987654320]+'
Wort0815
Wort47
Wort6279
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep -E  'Wort[987654320].[1]+'
Wort0815
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep -E  'Wort[987654320].[1]'
Wort0815
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep -E  'Wort[987654320].[02-9]'
Wort6279
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep -E --color  'Wort[987654320].[02-9]*'
Wort0815
Wort47
Wort6279
tux@debian11 ~$
tux@debian11 ~$ nl words.txt
    1       Wort
    2       Wort1
    3       Wort0815
    4       Wort47
    5       Wort6279
tux@debian11 ~$ #    >> Zeilen 1 und 2 fehlen, weil die Mindestlänge von 6 Zeichen erforderlich
tux@debian11 ~$ #    ist.
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep -E --color  'Wort[987654320].[02-9]*$'
Wort47
Wort6279
tux@debian11 ~$
tux@debian11 ~$ cat words.txt | grep -E --color  'Wort[987654320].[02-9]?$'
Wort47
tux@debian11 ~$

Der Einsatz des Plus-Quantifiers kann im Zusammenhang mit Logdateien sehr sinnvoll sein:

tux@debian11 ~$ ls /var/log | grep -Ei '^[a-z]+\.log$'
alternatives.log
bootstrap.log
dpkg.log
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ ls /var/log | grep -Ei --color '^[a-z]+\.log$'
alternatives.log
bootstrap.log
dpkg.log
tux@debian11 ~$
tux@debian11 ~$ ls /var/log | grep -Ei --color '^[a]+\.log$'
tux@debian11 ~$
tux@debian11 ~$ ls /var/log | grep -Ei --color '^[dgkp]+\.log$'
dpkg.log
tux@debian11 ~$
tux@debian11 ~$ #   >> Der Zeichenvorrat reicht genau nur für "dpkg".log
tux@debian11 ~$ #                                              ====
tux@debian11 ~$
tux@debian11 ~$ touch /var/log/dpkgz.log    ## Nachher wieder löschen!
tux@debian11 ~$
tux@debian11 ~$ ls /var/log | grep -Ei --color '^[dgkp]+\.log$'
dpkg.log
tux@debian11 ~$
tux@debian11 ~$ ls /var/log | grep -Ei --color '^[dgkpz]+\.log$'
dpkg.log
dpkgz.log
tux@debian11 ~$
tux@debian11 ~$ ls /var/log | grep -Ei --color '^[dgkpzobtar]+\.log$'
dpkg.log
dpkgz.log
tux@debian11 ~$
tux@debian11 ~$ ls /var/log | grep -Ei --color '^[dgkpzobstars]+\.log$'
bootstrap.log
dpkg.log
dpkgz.log
tux@debian11 ~$
tux@debian11 ~$ ls /var/log | grep -Ei --color '^[dgkpzobstars]*\.log$'
bootstrap.log
dpkg.log
dpkgz.log
tux@debian11 ~$
tux@debian11 ~$ ls /var/log | grep -Ei --color '[dgkpzobstars]*\.log$'
alternatives.log
bootstrap.log
dpkg.log
dpkgz.log
tux@debian11 ~$
tux@debian11 ~$ ls /var/log | grep -Ei --color '[dgkpzobstars]+\.log$'
alternatives.log
bootstrap.log
dpkg.log
dpkgz.log
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ ls -l /var/log/X*
ls: cannot access '/var/log/X*': No such file or directory
tux@debian11 ~$
tux@debian11 ~$ #   >> Dieser Linux-Container hat keine X-Oberfläche, also fehlen diese Dateien!

In einer kompletten Debian 11 Installation (Mit grafischer X-Oberfläche):

tux@bull:~$ cd /var/log
tux@bull:/var/log$
tux@bull:/var/log$ ls | grep --color -Ei '[a-o]+\.log$'
auth.log
daemon.log
dpkg.log
fontconfig.log
kern.log
vboxadd-install.log
tux@bull:/var/log$
tux@bull:/var/log$ ls | grep --color -Ei '[a-o]+\.log$' | wc -l
6
tux@bull:/var/log$
tux@bull:/var/log$ ls | grep --color -Ei '[a-z]+\.log$' | wc -l
11
tux@bull:/var/log$
tux@bull:/var/log$ ls | grep --color -Ei '[a-z]+\.log$' | grep X
tux@bull:/var/log$
tux@bull:/var/log$ ls -l Xorg.[0-9].log
-rw-r--r-- 1 root root 23885  7. Feb 14:55 Xorg.0.log
-rw-r--r-- 1 root root 30596 18. Jan 07:53 Xorg.1.log
tux@bull:/var/log$
tux@bull:/var/log$
tux@bull:/var/log$
tux@bull:/var/log$ ls | grep --color -Ei '[a-z]+.*\.log$' | grep X
Xorg.0.log
Xorg.1.log
tux@bull:/var/log$
tux@bull:/var/log$ ls | grep --color -Ei '[a-z]+.*\.log$' | wc -l
13
tux@bull:/var/log$
tux@bull:/var/log$
tux@bull:/var/log$
tux@bull:/var/log$ # Anstelle des Allround-Jokers '.*' nur '[.][0-9]' verwenden:
tux@bull:/var/log$ ls | grep --color -Ei '^[a-z]+.*\.log$' | tail -5
user.log
vboxadd-install.log
vboxadd-setup.log
Xorg.0.log
Xorg.1.log
tux@bull:/var/log$
tux@bull:/var/log$ ls | grep --color -Ei '^[a-z]+[.][0-9]\.log$' | tail -5
Xorg.0.log
Xorg.1.log
tux@bull:/var/log$
tux@bull:/var/log$ # Ohne '-i' (ignore case sensitivity) fehlen die beiden Dateien noch:
tux@bull:/var/log$ ls | grep --color -E '^[a-z]+[.][0-9]\.log$' | tail -5
tux@bull:/var/log$

Wenn wir nun aber das große ‚X‘ einfach mit die Zeichenklasse fürs erste Zeichen mit aufnehmen, finden wir die auf diesem X-Window-System vorhanden Logdateien wieder:

tux@bull:/var/log$ ls | grep --color -E '^[a-zX]+[.][0-9]\.log$' | tail -5
Xorg.0.log
Xorg.1.log
tux@bull:/var/log$
tux@bull:/var/log$
tux@bull:/var/log$ cd
tux@bull:~$

Und nochmal das Plus im Zusammenhang mit unserer ersten Übungsdatei:

tux@debian11 ~$ ## STERN:
tux@debian11 ~$ grep -Ei 'aa*' ankertest.txt
Am Anfang war das O.
Am Anfang war das Z.
Am Anfang war W
Alpha und Agemo.
Aaron an der Aare in Aargau
Aaaah - wie wunderbar
tux@debian11 ~$
tux@debian11 ~$ grep -Ei 'aaa*' ankertest.txt
Aaron an der Aare in Aargau
Aaaah - wie wunderbar
tux@debian11 ~$
tux@debian11 ~$ ## Im Unterschied zum Plus:
tux@debian11 ~$ grep -Ei 'aa+' ankertest.txt
Aaron an der Aare in Aargau
Aaaah - wie wunderbar
tux@debian11 ~$
tux@debian11 ~$ grep -Ei 'aaa+' ankertest.txt
Aaaah - wie wunderbar
tux@debian11 ~$

Fixed grep

Hier wird kein regulärer Ausdruck akzeptiert, das Suchmuster ist einfach ein fixes Muster:

tux@debian11 ~$ echo 'Ich habe Dollar$' >> words.txt
tux@debian11 ~$
tux@debian11 ~$ echo 'Zeile, die mit 'r' endet: Oper' >> words.txt
tux@debian11 ~$
tux@debian11 ~$ # Mit regex-Interpretation:
tux@debian11 ~$ grep 'r$' words.txt
Zeile, die mit r endet: Oper
tux@debian11 ~$
tux@debian11 ~$
tux@debian11 ~$ # Ohne regex-Interpretation:
tux@debian11 ~$ grep -F 'r$' words.txt
Ich habe Dollar$
tux@debian11 ~$