it-swarm.com.de

SED: Kopieren von Zeilen aus einer Datei in eine bestimmte Zeile in einer anderen Datei

Ich kann dies anhand des folgenden Beispiels machen. Der erste Befehl gibt die Zeilen 16 ... 80 von file1 bis patch aus, während der 2. Befehl den Inhalt von patch nach Zeile 18 in file2 einfügt:

sed -n 16,80p file1>patch
sed -i 18rpatch file2

Ich möchte jedoch direkt von einer Datei in eine andere kopieren, ohne eine temporäre Datei dazwischen zu verwenden, in einem Befehl mit sed (nicht awk usw.). Ich bin mir ziemlich sicher, dass das möglich ist, weiß nicht wie.

5
mYself

Um dies mit sed zu tun, sind einige zusätzliche Tricks der Shell erforderlich. Angenommen, bash könnte man verwenden

sed -i 18r<(sed '16,80!d' file1) file2

Dabei wird <(sed '16,80!d' file1) durch den Namen einer Pipe ersetzt, aus der die Ausgabe von sed '16,80!d' file1 gelesen werden kann.

Im Allgemeinen finde ich, dass es besser ist, dies mit awk zu tun (wenn auch etwas länger), da awk besser für die Verarbeitung mehrerer Eingabedateien geeignet ist. Zum Beispiel:

awk 'NR == FNR { if(FNR >= 16 && FNR <= 80) { patch = patch $0 ORS }; next } FNR == 18 { $0 = patch $0 } 1' file1 file2

Das funktioniert wie folgt:

NR == FNR {                       # While processing the first file
  if(FNR >= 16 && FNR <= 80) {    # remember the patch lines
    patch = patch $0 ORS
  }
  next                            # and do nothing else
}
FNR == 18 {                       # after that, while processing the first file:
  $0 = patch $0                   # prepend the patch to line 18
}
1                                 # and print regardless of whether the current
                                  # line was patched.

Dieser Ansatz eignet sich jedoch nicht für die direkte Bearbeitung von Dateien. Dies ist normalerweise kein Problem. Ich würde einfach verwenden

cp file2 file2~
awk ... file1 file2~ > file2

mit dem zusätzlichen Vorteil, eine Sicherung für den Fall zu haben, dass die Dinge birnenförmig sind, aber am Ende liegt es an Ihnen.

5
Wintermute

Ich habe etwas Ähnliches gemacht mit:

    head -80 file | tail -16 > patch

Überprüfen Sie die Dokumentation für Ihre lokalen Versionen von head und tail und ändern Sie die beiden Ganzzahlen entsprechend Ihren Anforderungen.

3
Arif Burhan

ich hatte dieses Problem, ich tat es in 2 Schritten (1-tail 2-head), zum Beispiel in einer Textdatei mit 20 Zeilen (test.txt). Wir möchten Zeilen von 13 bis 17 in eine andere Datei kopieren (final. TXT),

tail -8 test.txt> temp.txt
head -5 temp.txt> final.txt

0
Farshad Falaki
sed -i '1,15 d
        34 r patch
        81,$ d' YourFile

# oneliner version
sed -i -e '1,15 d' -e '34 r patch' -e '81,$ d' YourFile
  • zeilenreihenfolge ist nicht wichtig.
  • Sie können ein bisschen anpassen oder mit einer solchen Variable stapeln

sed -i "1,16 d $(( 16 + 18 )) r patch 81,$ d" YourFile

fügen Sie jedoch in diesem Fall etwas Sicherheit über die Zeilenzahl hinzu.

  • wenn die r-Zeile mehr als 1 Zeile ist, werden die folgenden Zeilen immer noch vom ursprünglichen Ort gezählt und die endgültige Datei ist größer als 80 - 16 Zeilen

ich prüfe nicht genau auf genommene, ausgeschlossene oder modifizierte Zeilen (wie 34 ist die 18. Zeile der zugeschnittenen Datei), aber das Prinzip ist dasselbe

In diesem Beispiel verwendete Indexreferenzen für Zeilen:

  • 1,15 ist die Überschriftenzeile, die entfernt werden soll. In diesem Fall werden die Pflegelinien von 16 verwendet
  • 34 ist die Zeile zum Ändern des Inhalts und ist das Ergebnis der 18. Zeile NACH dem ersten neuen Inhalt (Zeile 16 in unserem Fall), also 16 + 18 = 34
  • 81,$ sind nachfolgende Zeilen, die entfernt werden sollen, $ bedeutet die letzte Zeile und 81 ist die erste Zeile (nach 80, die genommen wird) der unerwünschten nachfolgenden Zeilen.
0
NeronLeVelu