(gelöst) filtern mit grep: zuviel oder zuwenig

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
michaa7
Beiträge: 4917
Registriert: 12.12.2004 00:46:49
Lizenz eigener Beiträge: MIT Lizenz

(gelöst) filtern mit grep: zuviel oder zuwenig

Beitrag von michaa7 » 12.07.2023 20:29:48

Ich versuche per grep (habe gaaaaaaanz kurz mal sed angeschaut) aus /etc/grub.d/40_custom nur die Namen meiner "menuentry/ies" per grep zu filtern

Code: Alles auswählen

# grep  -e "menuentry '[[:print:]][[:space:]]'" /etc/grub.d/40_custom
#

Code: Alles auswählen

# grep  "menuentry ''" /etc/grub.d/40_custom
#

Code: Alles auswählen

# grep  "menuentry '*'" /etc/grub.d/40_custom
menuentry 'siduction 2018.3.0 Patience (LXQt) GNU/Linux (on /dev/sdb2)' --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-/boot/vmlinuz-6.1.8-1-siduction-amd64--UUID-editiert' {
menuentry 'notinstallation' {
Was ich will ist

Code: Alles auswählen

grep <so-ist-das-kommando-richtig>
siduction 2018.3.0 Patience (LXQt) GNU/Linux (on /dev/sdb2)
notinstallation
Ich habe noch mehr Varianten versucht, aber ich verstehe nicht mal die hier warum sie ausgeben was sie ausgeben, trut manpage und beispielen aus dem Internet. Ich versteh nicht warum "{" irgendwie mit meinem Suchmuster korrespondiert, noch warum "'*'" das Endresultat nicht beim zweiten "'" abbricht.

Code: Alles auswählen

~# grep -o "menuentry '*'" /etc/grub.d/40_custom
menuentry '
menuentry '
ist auch nicht was ich will.

Hat hier jemand nen Gedankenschubser parat?
Zuletzt geändert von michaa7 am 13.07.2023 11:16:52, insgesamt 1-mal geändert.
gruß

michaa7

-------------------------------
Menschen ändern gelegentlich ihre Ansichten, aber nur selten ihre Motive. (Oskar Negt)

tobo
Beiträge: 2336
Registriert: 10.12.2008 10:51:41

Re: filtern mit grep: zuviel oder zuwenig

Beitrag von tobo » 12.07.2023 20:50:37

Wie ist es damit:

Code: Alles auswählen

grep -oP "(?<=^menuentry ')[^']+"
//oder
sed -E "s/^menuentry '([^']+).*/\1/"
Edit:
Normalerweise gibt man eine (genügend umfangreiche) Eingabe (ich z.B. habe eine nichtssagende /etc/grub.d/40_custom) und die erwartete Ausgabe an!
Ich versteh nicht warum "{" irgendwie mit meinem Suchmuster korrespondiert, noch warum "'*'" das Endresultat nicht beim zweiten "'" abbricht.
Eine Vermutung: { korrespondiert, weil zuvor beim ' gierig ausgewertet wurde (alles bis zum letzten (nicht ersten) ') und * ist ein Quantor und bezieht sich ausschließlich (anders als alleinstehend in der Shell) auf das Zeichen davor. Auf genauere Rückfragen gerne auch genauere Beschreibungen...

michaa7
Beiträge: 4917
Registriert: 12.12.2004 00:46:49
Lizenz eigener Beiträge: MIT Lizenz

Re: filtern mit grep: zuviel oder zuwenig

Beitrag von michaa7 » 12.07.2023 22:34:45

1) Danke

2)

Code: Alles auswählen

$ grep -oP "(?<=^menuentry ')[^']+" /etc/grub.d/40_custom
siduction 2018.3.0 Patience (LXQt) GNU/Linux (on /dev/sdb2)
notinstallation
funktioniert exakt wie es gewünscht ist!

Das werde ich mir Stück für Stück anschauen und versuchen die Befehlskette in ihren Einzelteilen zu verstehen . auf den ersten Blick glaube ich nur zwei Verneinungen zu sehen der Rest ist noch ein Rätsel ... ich schau mal wie weit ich komme.

Dass "*" anders fuznktioniert als in der Shell wollte ich offenbar nicht glauben, die Erklärung dazu stimmt aber wohl so wie es eben ist.

3)
Der sed Befehl funktioniert nicht: Der Vorderteil wird zwar richtig begrenzt, aber nach "...sdb2)" bzw. "notinstallation" wird nicht abgeschnitten.

Danke nochmals, werde mit wie gesagt die grep Sequenz genauer anschauen. Melde mich die Tage wo ich nicht weiterkomme ...

Ok, gleich doch noch eine Frage:
grep -P bedeutet ja, das Perl regexe verwendet werden.
Heißt das dass ich die man grep im wesentlichen vergessen kann und irgendwo (wo?) suchen muß um die Zeichenkette verstehen zu können?
gruß

michaa7

-------------------------------
Menschen ändern gelegentlich ihre Ansichten, aber nur selten ihre Motive. (Oskar Negt)

Benutzeravatar
thunder11
Beiträge: 2148
Registriert: 19.04.2023 09:08:30

Re: filtern mit grep: zuviel oder zuwenig

Beitrag von thunder11 » 12.07.2023 22:47:51

Oder mit cut (ich komm mit den Hieroglyphen nicht so richtig klar :facepalm: :

Code: Alles auswählen

$ grep menuentry /etc/grub.d/40_custom|cut -c 12-50
Debian SID Xfce" {
 "Debian SID Xfce ohne Chain" {
 "Debian SID von OS"{

tobo
Beiträge: 2336
Registriert: 10.12.2008 10:51:41

Re: filtern mit grep: zuviel oder zuwenig

Beitrag von tobo » 12.07.2023 23:12:39

michaa7 hat geschrieben: ↑ zum Beitrag ↑
12.07.2023 22:34:45
Der sed Befehl funktioniert nicht: Der Vorderteil wird zwar richtig begrenzt, aber nach "...sdb2)" bzw. "notinstallation" wird nicht abgeschnitten.
Hmm. Mein vermutetes Ausgangsmaterial:

Code: Alles auswählen

$ echo "menuentry 'siduction 2018.3.0 Patience (LXQt) GNU/Linux (on /dev/sdb2)' --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-/boot/vmlinuz-6.1.8-1-siduction-amd64--UUID-editiert' {
menuentry 'notinstallation' {" | sed -E "s/^menuentry '([^']+).*/\1/"
siduction 2018.3.0 Patience (LXQt) GNU/Linux (on /dev/sdb2)
notinstallation
$
Danke nochmals, werde mit wie gesagt die grep Sequenz genauer anschauen. Melde mich die Tage wo ich nicht weiterkomme ...
Stichwort: "Positiv Lookbehind" (positive rückwirkende Zusicherung). Die allgemeine Form '(?<=a)b' bedeutet: Finde b, wo a vorangeht. a hat dabei eine feste Breite (fixed String -> kein Quantor: *?+); das Ergebnis ist nur b und a wird dabei nicht "verbraucht":

Code: Alles auswählen

$ echo "ab12" | grep -oP '(?<=a)b|(?<=ab)1'
b
1
$
Ok, gleich doch noch eine Frage:
grep -P bedeutet ja, das Perl regexe verwendet werden.
Heißt das dass ich die man grep im wesentlichen vergessen kann und irgendwo (wo?) suchen muß um die Zeichenkette verstehen zu können?
grep kann man nicht vergessen, man erhält halt Optionen (Paket: perl-doc). Siehe:

Code: Alles auswählen

man perlre

michaa7
Beiträge: 4917
Registriert: 12.12.2004 00:46:49
Lizenz eigener Beiträge: MIT Lizenz

Re: filtern mit grep: zuviel oder zuwenig

Beitrag von michaa7 » 13.07.2023 00:04:54

ok, "man perlre" kannte ich nicht. Habe im Netz nach man PCRE gesucht und https://www.pcre.org/original/doc/html/pcrepattern.htm
gefunden.

Damit, und mit ausprobieren, habe ich mir bis jetzt folgendes zusammengereimt:

grep: naja, das Command
-oP; o zeigt nur die passende Teile, nicht alle passenden ZEilen an; P verwendet Perlregexe;

Jetzt wurde es schwieriger:
Der gesammte Ausdruck benötige " als Begrenzer des zu matchenden Suchstrings, ( und ) begrenzen einen Teilstring, ?<= gibt an dass dem Match der mit ^beginnende String vorausgehen muss.

Soweit versteh ich wie der Anfang des Gesuchten Musters gefunden wird. Mit dem Ende tue ich mich noch schwer: [] gib ja ein classe an ^ negiert dieses Ergebnis, hier '
Warum dies das Ende des gesuchten Musters definiert verstehe ich nicht. Ich kann es mir nur so erklären, dass es vllt so funktioniert das sobald die zweite Bedingung ( kein ') erfüllt ist die weiteres Suche abgebrochen wird und + dann dafür sorgt das alles zwischen den beiden Ereignissen angezeigt wird. Wobei ich da nicht verstehe warum die -o Option und das + notwendig sind (was sie definitiv sind).

Einiges verstanden, aber eben noch nciht alles.

@ thunder11
Die cut variante schaut, ohne dass ich mich jetzt näher damit befaßt habe, so aus, dass man das ergebnis Kennen muß um 12-50 festlegen zu können, oder wie kommt man darauf? Die { sind auch nciht was man möchte, ansonsten recht schlank ...
gruß

michaa7

-------------------------------
Menschen ändern gelegentlich ihre Ansichten, aber nur selten ihre Motive. (Oskar Negt)

tobo
Beiträge: 2336
Registriert: 10.12.2008 10:51:41

Re: filtern mit grep: zuviel oder zuwenig

Beitrag von tobo » 13.07.2023 00:24:30

Code: Alles auswählen

"(?<=^menuentry ')[^']+"
Man zerlegt die Zeilen (ab Zeilenanfang ^) in:
menuentry '
gefolgt von maximal vielen:
Nicht '
. Ein Ende des gesuchten Musters wird dann (exklusive) erreicht, wenn ein ' folgt (möglichst viele Nicht-') . -o gibt nicht die gefunde Zeile (Standardverhalten von grep), sondern nur den Match b (bei (?<=a)b) aus. Und wie positive lookbehind schon klingt - es gibt alle Kombinationen von positive/negative lookahead/lookbehind.

Das ist regex-technisch bestimmt nicht trivial und die sed-Lösung wäre einfacher, sofern sie funktioniert...

michaa7
Beiträge: 4917
Registriert: 12.12.2004 00:46:49
Lizenz eigener Beiträge: MIT Lizenz

Re: filtern mit grep: zuviel oder zuwenig

Beitrag von michaa7 » 13.07.2023 01:37:02

Das Ausgangsmaterial ist länger und hat Zeilenumbrüche, Bedingungen etc. In soweit war das für dich natürlich partieller Blindflug. Das wie du schreibst nicht so triviale grep/perl Konstrukt stolpert da wohl nicht weil die Endbedingung greift und der Rest keinen Rolle spielt

Code: Alles auswählen

#!/bin/sh
exec tail -n +3 $0
# This file provides an easy way to add custom menu entries.  Simply type the
# menu entries you want to add after this comment.  Be careful not to change
# the 'exec tail' line above.

#manuelle Kopie aus /boot/grub/grub.cfg### BEGIN /etc/grub.d/30_os-prober ###
menuentry 'siduction 2018.3.0 Patience (LXQt) GNU/Linux (on /dev/sdb2)' --class gnu-linux --class gnu --class os $menuentry_id_option 'gnulinux-/boot/vmlinuz-6.1.8-1-siduction-amd64--UUID-editiert' {
                insmod part_msdos
                insmod ext2
                set root='hd1,msdos2'
                if [ x$feature_platform_search_hint = xy ]; then
                  search --no-floppy --fs-uuid --set=root --hint-bios=hd1,msdos2 --hint-efi=hd1,msdos2 --hint-baremetal=ahci1,msdos2 --hint='hd1,msdos2'  UUID-editiert
                else
                  search --no-floppy --fs-uuid --set=root UUID-editiert
                fi
                linux /boot/vmlinuz-6.1.8-1-siduction-amd64 root=UUID=UUID-editiert ro quiet systemd.show_status=1
                initrd /boot/initrd.img-6.1.8-1-siduction-amd64
        }

menuentry 'notinstallation' {
search --no-floppy --fs-uuid --set=root UUID-editiert
linux /vmlinuz root=UUID=UUID-editiert
Und BTW, gute kompakte Erklärung der Mustererkennung mit grep. Danke. Das hilft sehr. Auch wenn mir das als Tropfen aus einem Ozean erscheint.
gruß

michaa7

-------------------------------
Menschen ändern gelegentlich ihre Ansichten, aber nur selten ihre Motive. (Oskar Negt)

tobo
Beiträge: 2336
Registriert: 10.12.2008 10:51:41

Re: filtern mit grep: zuviel oder zuwenig

Beitrag von tobo » 13.07.2023 01:47:36

Jedesmal dasselbe - nachts bekomme ich gedanklich nur noch die Hälfte mit:

Code: Alles auswählen

sed -En "s/^menuentry '([^']+).*/\1/p"
Auch wenn mir das als Tropfen aus einem Ozean erscheint.
Glaubst du, dass das irgendwem anfangs anders gegangen ist?

michaa7
Beiträge: 4917
Registriert: 12.12.2004 00:46:49
Lizenz eigener Beiträge: MIT Lizenz

Re: filtern mit grep: zuviel oder zuwenig

Beitrag von michaa7 » 13.07.2023 11:16:30

tobo hat geschrieben: ↑ zum Beitrag ↑
13.07.2023 01:47:36
Jedesmal dasselbe - nachts bekomme ich gedanklich nur noch die Hälfte mit:

Code: Alles auswählen

sed -En "s/^menuentry '([^']+).*/\1/p"
Das funktioniert. Danke. Werde ich mir heute Abend mal zusammenfummeln ....
Auch wenn mir das als Tropfen aus einem Ozean erscheint.
Glaubst du, dass das irgendwem anfangs anders gegangen ist?
Nein. Aber die Größe des Ozeans ist schon abschreckend beeindruckend ... um so hilfreicher deine focusierte Erklärung.
gruß

michaa7

-------------------------------
Menschen ändern gelegentlich ihre Ansichten, aber nur selten ihre Motive. (Oskar Negt)

Huo
Beiträge: 778
Registriert: 26.11.2017 14:03:31
Wohnort: Freiburg

Re: (gelöst) filtern mit grep: zuviel oder zuwenig

Beitrag von Huo » 14.07.2023 09:29:25

Für mich als kleine Übungsaufgabe habe ich es noch mit awk umgesetzt:

Code: Alles auswählen

$ awk -F "'" '/^menuentry '\''.+/ {print $2}' test.txt
siduction 2018.3.0 Patience (LXQt) GNU/Linux (on /dev/sdb2)
notinstallation

tobo
Beiträge: 2336
Registriert: 10.12.2008 10:51:41

Re: (gelöst) filtern mit grep: zuviel oder zuwenig

Beitrag von tobo » 14.07.2023 12:47:57

Wenn man z.B. direkten (-o0..n) Zugriff auf etwaige capturing groups haben will, dann ist pcregrep optimal:

Code: Alles auswählen

pcregrep -o "^menuentry '([^']+)"
Das Ergebnis ist wie oben.

Antworten