So extrahieren Sie bestimmte Daten aus einer Zeile

7

Problem

Ich habe nach einer Lösung in Bash gesucht, die bestimmte Informationen nach einer bestimmten Zeichenfolge extrahieren kann.

Beispiel

Zum Beispiel (vom Laufen acpi):

Battery 0: Discharging, 37%, 01:33:20 remaining

Wie kann ich den Prozentsatz nach der Entlassung extrahieren? In diesem Fall wäre es 37%...

Anmerkungen

Ich suche nach einer einfachen Lösung, die keine Reihe von Befehlsargumenten erfordert.

NerdOfCode
quelle

Antworten:

9

Ich bin mir nicht sicher, was Sie mit "eine Lösung in Bash" meinen, awkkann aber den Job machen:

awk -F", " '{print$2}'
  • -F", "- Wählen Sie ein Komma gefolgt von einem Leerzeichen als FFeldtrennzeichen. Dadurch wird Ihre Beispielzeile in drei Spalten aufgeteilt, wobei sich die zweite befindet37%
  • '{print$2}' - Drucken Sie die zweite Spalte

Oder wie wäre es sed?

sed -E 's/.* ([0-9]+%).*/\1/'
Dessert
quelle
Wenn Sie das awkBeispiel erklären könnten , wäre das großartig. Ich hatte vor, nur damit herumzuspielen, aber eine Erklärung wäre besser.
NerdOfCode
Das einzige, was ich nicht verstehe, sind die Klammern, die in der {}'{print$2}'
Endanweisung
@NerdOfCode Das liegt daran, dass es sich um eine Aktionsanweisung handelt, siehe MUSTER UND AKTIONEN in man awk.
Nachtisch
13

Hier sind ein paar:

$ acpi | grep -oP '\d+%'
99%
$ acpi | awk -F',' '{print $2}'
 99%
$ acpi | perl -pe 's/.*?(\d+%).*/$1/'
99%
Terdon
quelle
7

Ich habe nach einer Lösung in bash gesucht, die bestimmte Informationen nach einer bestimmten Zeichenfolge extrahieren kann.

Nach einer bestimmten Zeichenfolge? Keine der beiden zuvor veröffentlichten Antworten tut dies speziell (da das Abrufen von Text nach einer Zeichenfolge nicht der beste Weg ist, um die Informationen zu erhalten, die Sie in Ihrem Beispiel gewünscht haben).

Hier sind einige Möglichkeiten, um Text nach einer Zeichenfolge abzurufen. Ich habe Ihr Beispiel verwendet, obwohl Dessert Antwort und Antwort des terdon beide geeignetere Ansätze auf diesen speziellen Fall zu demonstrieren.

Verwendung \Kvon Perl, zum Beispiel in grepmit -P(Perl-Regex zulassen) und -o(nur Übereinstimmung):

grep -Po 'string\Kdesired'

Wo stringist ein Ausdruck, der mit dem übereinstimmt, was vor dem steht, was Sie wollen, und wo desiredein Ausdruck mit dem übereinstimmt, was Sie ausgeben möchten? Dies ist nützlich, wenn das gewünschte Muster an einer anderen Stelle in der Datei / Zeile vorkommt (z. B. ist es eine Zahl und die Datei / Zeile enthält andere Zahlen). In Ihrem Beispiel könnte dies etwa so aussehen:

$ acpi | grep -Po 'ing, \K[^,]+'
79%

[^,]+bedeutet einige Zeichen, die kein Komma sind, so dass Text bis zu einem Komma erfasst werden kann. Wir könnten auch ...drei beliebige Zeichen verwenden, aber wie in einem Kommentar von PerlDuck ausgeführt , ist es möglich, dass das gewünschte Muster hier mehr oder weniger als drei Zeichen enthält.

In sedkönnen Sie Erfassungsgruppen mit (und verwenden ):

sed -r 's/.*string(desired).*/\1/' 

wo \1ist was mit gerettet wurde ( ). Für Ihr Beispiel:

$ acpi | sed -r 's/.*ing, ([^,]+).*/\1/'
89%

Hier ist eine Möglichkeit, dies nur mit Bash in Ihrem Beispiel zu tun

$ output=$(acpi); string="${output#*ing, *}"; desired="${string%,*}"; echo "$desired"
96%

${var#string*}schneidet varvor string(einschließlich) und ${var%string*}schneidet varnach string(einschließlich).

Dies ist keine vollständige Liste. Es gibt viele Möglichkeiten, dies zu tun :)

Zanna
quelle
Wow, das ist eine wirklich detaillierte Antwort mit tollen Erklärungen, danke, aber ich fürchte, @dessert hat dich schon geschlagen ...
NerdOfCode
Das Abgleichen von drei Zeichen (wie in (...)) kann unangemessen sein, wenn der Prozentsatz unter 10 liegt. Oder 100.
PerlDuck
1
@PerlDuck guter Punkt! bearbeitet :)
Zanna
6

Eine Bash-Lösung, wie gewünscht, ohne unangenehme Awkismen oder sedulierende Sedismen:

my_battery=( $(acpi) ); echo ${my_battery[3]}

Dies verwendet die Befehlssubstitution, erstellt ein Array der Befehlsausgabe und zeigt das 4. Element des Arrays an.

Dies funktioniert mit der Ausgabe von acpi, die anscheinend immer den Batterieprozentsatz als 4. Parameter hat. Wenn Sie das Element des Arrays nach "Entladen" suchen möchten, erhalten Sie kein Ergebnis, wenn acpi "Batterie 0: Voll, 100%" anzeigt.

Wastrel
quelle