Ich habe eine Konfigurationsdatei im folgenden Format.
<Title>
[part1]
A.File = a
A.Val = val1
B.File = a
B.Val = val1
[part2]
A.File = a1
A.Val = val2
B.File = a
B.Val = val1
Ich möchte nur Werte aus dem ersten Teil extrahieren.
#!/bin/sh
getCalibDate()
{
file="/path/of/config/file"
value=`cat ${file} | grep Val | cut -d'=' -f2`
for v in $value
do
echo $v
done
}
getCalibDate
Das obige Skript gibt alle Werte zurück. Wie kann ich nur Werte aus dem ersten Teil (Teil 1) erhalten?
shell
text-processing
user3153014
quelle
quelle
cat file | grep foo
sinnlos ist. Es ist bekannt als "nutzlose Verwendung von Katze" . Sie könnengrep foo file
stattdessen immer tun .${file}
statt nur einfach$file
ist gelegentlich nützlich, aber es ist viel nützlicher, sich daran zu gewöhnen, zu sagen"$file"
. Das Sprichwort${file}
schützt Sie nicht vor Leerzeichen oder Platzhalterzeichen$file
.Antworten:
Wenn Sie nur 4 Zeilen haben
[part1]
, können Sie die-A4
Option verwenden mitgrep
:Für den allgemeinen Fall (mehr als 4 Zeilen nach [Teil1]) verwenden Sie
sed
, um den Text zwischen zwei Teilen abzurufen :head
istpart2
am Ende zusätzlich zu löschenWie Terdon sagte, müssen Sie nicht verwenden
cat
, können Sie stattdessen Folgendes tun:ODER:
quelle
Sie müssen ein komplexeres Tool verwenden, um die Datei zu analysieren. Zum Beispiel
awk
:Hier wird die Variable
a
jedes Mal erhöht, wenn eine Zeile übereinstimmt[part
. Dann wird das letzte Feld ($NF
) gedruckt, wenn eine Zeile übereinstimmt,Val
aber nur, wenna
es kleiner als 2 ist, nur wenn wir uns im 1. Abschnitt befinden.quelle
awk
ist einfach ein erstaunliches Werkzeugawk
. Zum Beispiel einer der ersten Algorithmen zur Genvorhersage.cut -d'=' -f2
, was das=
zweitbegrenzte Feld ergibt . Ihre Antwort ergibt das letzte durch Leerzeichen getrennte Feld. Sie sind für die Beispieldaten in der Frage gleich, es handelt sich jedoch um Beispieldaten . Ich frage mich, wie die realen Daten aussehen.awk -F= '{print $2}'
was dasselbe tut, aber ich fand, dass$NF
dies in diesem Fall einfacher war.und benutze dies:
AUSGABE ist:
quelle
So erhalten Sie die gesamten Zeilen aus dem ersten Teil:
So drucken Sie einfach die rechte Seite der ersten
=
:quelle
Hier gibt es einige gute Antworten, aber ich sehe nur eine, die den
Val
Teil des Problems enthält, und es ist nicht eindeutig, ob dies richtig ist. Ich bin damit einverstanden, dass diesawk
„ein erstaunliches Werkzeug“ ist, aber hier ist es nicht notwendig. Ich glaube, dass diesersed
Befehl:wahrscheinlich macht was gewünscht. Wie die anderen
sed -e '/\[part1\]/,/\[part2\]/p'
Lösungen ( Networker und Babyy ) ist dies trivial anpassbar, um einen beliebigen Abschnitt auszuwählen. (Sie müssen natürlich den Namen kennen. Wenn Sie nur die Ordnungszahl kennen, können Sie die Antwort von terdon oder die Antwort von glenn jackman anpassen. Beide zählen Abschnitte, anstatt nach einem bestimmten Namen zu suchen.) Wenn Sie dies nicht tun Kennen Sie den Namen des folgenden Abschnitts, können Sie tunzum Beispiel.
Meine einzige Meta-Frage betrifft den
cut -d'=' -f2
Teil der Frage. Wenn eine Eingabezeile, aus der wir Daten extrahieren, mehrere=
Zeichen nach enthältVal
(dh der Feldwert enthält=
Zeichen), z.dann
cut
extrahiert der obige Befehl nur den Text zwischen dem ersten und dem zweiten=
(dh dem Feldwert bis zum ersten (aber nicht einschließlich) dem ersten=
), zE
. Dersed
Befehl, den ich oben dargestellt habe, extrahiert nur den Text nach dem letzten=
(zmc^2
. B. ). Verwenden Sie, um alles nach dem ersten=
(z. B.E=mc^2
) zu erhaltenVerwenden Sie, um das Verhalten von
cut
(z. B.E
) nachzuahmenBeachten Sie, dass mein Ansatz davon ausgeht, dass die Daten zumindest allgemein der Abbildung in der Frage entsprechen. dh mindestens eine
=
erscheint irgendwo rechts von derVal
Zeichenfolge. Dementsprechend werden alle meine Lösungen Eingaben wie ignorierenauch wenn es zwischen
[part1]
und fällt[part2]
.quelle
cut
Teilungen gleich sind und nur das zweite Feld der Zeile gedruckt werden und - wie Sie wahrscheinlich vorschlagen - mehr als übereinstimmende Felder vorhanden sind, behandelt Ihr altes das Problem der letzten drei übereinstimmenden Felder. Und so ahmt Ihr Befehl nicht nachcut
.s/.*
... Wenn Sie dies tun, wird nur das letztmögliche Vorkommen von erhaltenVal[^=]*=\([^=]*\).*/\1
. Scheint, als hättest du es nur dafür viel ausgearbeitet.Val…=…Val…=
" fehlschlägt ? Wenn ja, haben Sie wohl Recht. Ich habe diesen Fall nicht berücksichtigt. Aber in Ihrem ersten Kommentar gibt es nichts, was darauf hindeutet, dass Sie darüber sprechen, und Ihr zweiter Kommentar ist noch lange nicht klar.AUSGABE
Das sollte den Trick machen.
q
Die Eingabedatei wird sofort angezeigt, wenn sie zum ersten Mal irgendwo in der Eingabe auf die Zeichenfolge part2 trifft . Dies bedeutet, dass niemals versucht wird, die Teile der Datei zu lesen, die Sie nicht möchten - was sie sehr effizient machen sollte.Das
-n
deaktiviert das automatische Drucken, sodasssed
nur das gedruckt wird, was definitiv zum Drucken aufgefordert wirdp
. Das einzige Mal, dass es definitiv zum Drucken aufgefordert wird, ist, wenn eine Folge von 0 oder mehr Zeichen, die nicht vorhanden sind,=
und einem Zeichen, das ein Zeichen ist, erfolgreich entfernt werden kann=
.Wenn Sie stattdessen die gesamte übereinstimmende Zeile drucken möchten, können Sie Folgendes tun:
quelle