Extrahieren Sie mit sed einen Teil einer Zeile aus einer Datei

18

Ich möchte einen Teil einer Zeile aus einer Datei lesen. Beispielsweise:

POP3_SERVER_NAME = localhost

Ich möchte nur localhostmit sed zurückkehren.

Dieser Text steht in der dritten Zeile. Ich mache das, um die Zeile zu extrahieren:

sed -n '3p' installation.sh

Wie extrahiere ich nur den localhostTeil?

Mercer
quelle

Antworten:

26

awk könnte hier ein besseres Werkzeug sein.

$ cat test.dat
LINE 1
LINE 2
POP3_SERVER_NAME = localhost

Suchen Sie nach Zeilen, die "POP3_SERVER_NAME" enthalten. Drucke das letzte Feld. Dies hängt nicht davon ab, dass POP3_SERVER_NAME immer in Zeile 3 ist, was wahrscheinlich eine gute Sache ist.

$ awk '/POP3_SERVER_NAME/{print $NF}' test.dat
localhost

Abhängig von Ihrer Anwendung müssen Sie den regulären Ausdruck möglicherweise strenger gestalten. Beispielsweise möchten Sie möglicherweise nur die Zeile abgleichen , die mit POP3_SERVER_NAME beginnt .

$ awk '/^POP3_SERVER_NAME/{print $NF}' test.dat
localhost

Sed zu benutzen ist etwas weniger intuitiv. (Danke, mir ist die Ironie bewusst.) Adressieren Sie die Zeile, die POP3_SERVER_NAME enthält, an einer beliebigen Stelle. Ersetzen Sie den gesamten Text vom Zeilenanfang bis zum optionalen Leerzeichen nach "=" durch eine leere Zeichenfolge. Dann drucken.

sed -n -e '/POP3_SERVER_NAME/ s/.*\= *//p' test.dat
Mike Sherrill 'Cat Recall'
quelle
2
Der awkBefehl ist nett - aber nur, wenn Sie Leerzeichen haben =. Es wird nicht funktionieren POP3_SERVER_NAME=localhost.
Marcel Stör
2
@Marcel, Sie können das Trennzeichen, das von awkLeerzeichen verwendet wird, durch ein anderes Trennzeichen ersetzen -F. Zum Beispiel: -F "="Wird =in dem von Ihnen erwähnten Fall als Begrenzer verwendet.
Mattpr
7

Ersetzen Sie den pBefehl durch eine Ersetzung, die den unerwünschten Teil der Zeile entfernt.

sed -n '3 s/^[^=]*= *//p' installation.sh

Möglicherweise möchten Sie die Zeile nach Schlüsselwort und nicht nach Position abgleichen.

sed -n 's/^ *POP3_SERVER_NAME *= *//p' installation.sh
Gilles 'SO - hör auf böse zu sein'
quelle
5
echo "POP3_SERVER_NAME = localhost" | sed 's/.*= //'
localhost

Oder wenn Sie den Inhalt in einer Datei haben:

sed 's/.*= //' somefile.txt
localhost
Adam Siemion
quelle
ok, aber ich in meiner Datei wie folgt lesen: sed -n '3p' installation.sh
Mercer
2
@ Mercer - siehe die Updates, die ich der Antwort hinzugefügt habe.
SLM
@Adam Siemion - danke, aber wie soll die Zeilennummer angegeben werden?
Mercer
5

Sieht so aus, als hättest du eine Konfigurationsdatei. Was Sie tun könnten, ähnelt dem, was Adam Siemeon / slm vorschlagen:

sed -nr 's/[^=]+=\s*(.+)$/\1/p' filename

wo [^=]schließen alle ‚=‘ Zeichen, +sagt einer oder mehr von der gleichen Art von Zeichen, das durch eine tatsächliche gefolgt =, \sjeder Leerraum (einschließlich Laschen \tund neue Linien \n, \r\nund ebene Bereiche sind ‚‘, wohingegen *Mittel null oder mehr des gleichen Typs In Klammern wird angegeben, was enthalten ist, um die übereinstimmenden Zeichenfolgen in die Ersetzungsplatzhalter \ 1, \ 2, ..., \ n zu setzen $. Dies bedeutet das Ende einer Zeile. Dies folgt dem typischen Ersetzungsmuster von:. s/.../.../modifiersDie Befehlszeilenoption -rsteht für Erweiterte Regex-Syntax (aus Bequemlichkeitsgründen) und -nbedeutet, dass nichts ausgegeben wird, bis oder solange dies nicht ausdrücklich angefordert wird. Der pModifikator gibt das Ergebnis aus.

Sie können eine globale Suche mit dem gModifikator wie folgt durchführen:

sed -nr 's/[^=]+=\s*(.+)$/\1 /pg' filename  # note the space after \1

so dass Sie einen String erhalten , getrennt durch ' '(könnte \n, \toder was auch immer) , die Sie leicht verarbeiten können.

Beides gilt, vorausgesetzt, Ihre Werte, denen das Gleichungszeichen vorangestellt ist, erstrecken sich bis zum Ende einer Zeile und werden nicht von Kommentaren oder anderen Zeichen gefolgt, deren Semantik von einem einfachen "Wert" abweicht.


Bearbeiten:

Ich kann hier noch keine Kommentare zu anderen Posts abgeben. Um die Zeile anzuzeigen, übergeben Sie einfach die Zeilennummer (in Ihrem Fall 3) vor soder vor dem einleitenden Anführungszeichen (genau wie in vim).

sed -nr '3s/[^=]+=\s*(.+)$/\1/p' filename

Bitte werfen Sie einen Blick auf info sed. Zum Beispiel sind 3.2 und 4.7 für Sie von besonderem Interesse.

Nikolaus
quelle
4

Sie können den Befehl cut verwenden, indem Sie den Begrenzer auf '=' setzen und dann das zweite Feld wie folgt drucken:

cut -d'=' -f2
anselal
quelle
3

Mehrere Möglichkeiten, dies zu tun, wenn man bedenkt, dass Ihre Datei aufgerufen wird foobar:

Geben Sie das zu suchende Muster an:

PAT=POP3_SERVER_NAME

Mit extrahieren sed

sed -n "/$PAT/p" foobar | sed "s/$PAT = //"

Oder mit sedundcut

sed -n "/$PAT/p" foobar | cut -d' ' -f3
entmutigen
quelle
2

Das Schöne an Linux / Unix ist, dass es normalerweise mehr als einen Weg gibt, um etwas zu erreichen. Im Fall der Operation gibt es mindestens vier verschiedene Möglichkeiten, den POP-Servernamen aus der Datei zu extrahieren:

  1. grep POP3_SERVER_NAME installation.sh | cut -d'=' -f2
  2. grep POP3_SERVER_NAME installation.sh | awk '{print $3}'
  3. grep POP3_SERVER_NAME installation.sh | sed 's/.*= //'
  4. sed -n 's/^.*POP3_SERVER_NAME = //p' installation.sh
thdoan
quelle