2017-12-02 40 views
5

Ich schaute auf andere Antworten in Bezug auf Suchen und Ersetzen, aber ich kann einfach nicht die Muster verstehen.So suchen und ersetzen Sie mehrere Zeilen mit mehreren Zeilen

Wie kann ich diesen Teil einer Datei zu ändern (Zeilennummern 153 ... 156)

 let view = string.utf8 
     offset.pointee += string.substring(to: range.lowerBound).utf8.count 
     length.pointee = Int32(view.distance(from:range.lowerBound.samePosition(in: view), to:range.upperBound.samePosition(in: view))) 
     return token 

und ersetzen Sie es mit den folgenden Zeilen?

 let view:String.UTF8View = string.utf8 

     if let from = range.lowerBound.samePosition(in: view), 
      let to = range.upperBound.samePosition(in: view) { 
      offset.pointee += Int32(string[string.startIndex..<range.lowerBound].utf8.count) 
      length.pointee = Int32(view.distance(from: from, to: to)) 
      return token 
     } else { 
      return nil 
     } 
+0

Sind die Nummern 153-156 Teil der Eingabedatei? Oder hast du sie hier nur zur Veranschaulichung gezeigt? – PerlDuck

+0

zeigte sie nur zur Illustration – sirvon

+0

Müssen Sie streng Linien 153..156 ersetzen, oder den Code, den Sie zeigen (die in diesen Zeilen sein kann oder nicht)? – zdim

Antwort

4

Dies könnte für Sie arbeiten (GNU sed & Bash):

sed $'153r replacementFile\n;153,156d' file 

oder für die meisten seds:

sed -e '153r replacementFile' -e '153,156d' file 

oder wenn Sie es vorziehen:

sed '153,156c\  let view:String.UTF8View = string.utf8\ 
    if let from = range.lowerBound.samePosition(in: view),\ 
     let to = range.upperBound.samePosition(in: view) {\ 
     offset.pointee += Int32(string[string.startIndex..<range.lowerBound].utf8.count)\ 
     length.pointee = Int32(view.distance(from: from, to: to))\ 
     return token\ 
    } else {\ 
     return nil\ 
    }' file 

N. B. Die erste \ behält führende Leerzeichen und jede nachfolgende Zeile mit Ausnahme der letzten muss mit \ angefügt werden.Die Abschrift in SO formatiert nicht richtig, wenn eine leere Zeile durch eine einzige \ dargestellt wird (also entfernte ich die zweite Zeile der Ersetzung), aber die meisten Shells sollten.

1

sed wahrscheinlich das beste Werkzeug dafür ist,

vorausgesetzt, Ihr Ersatztext in der Datei ist

replace.txt
$ sed '153,156{153{r replace.txt 
        }; d}' file 

nur Arbeit für GNU könnte sed

2

Wenn Sie habe nicht GNU-sed für @ karafkas Antwort und möchte nur Zeilen mit exakten Zeilennummern ändern, du könntest auch die ed verwenden. Dieses

ed -s file <<'EOF' 
153,156c 
     let view:String.UTF8View = string.utf8 

     if let from = range.lowerBound.samePosition(in: view), 
      let to = range.upperBound.samePosition(in: view) { 
      offset.pointee += Int32(string[string.startIndex..<range.lowerBound].utf8.count) 
      length.pointee = Int32(view.distance(from: from, to: to)) 
      return token 
     } else { 
      return nil 
     } 
. 
w 
q 
EOF 
1

ist ein sehr gutes Beispiel für die Anwendung der Tie::File module, die die Zeilen einer Textdatei ein Array abbildet, so dass alle Änderungen an den Array machen werden in der Plattendatei widerspiegeln. Es ist ein Kernmodul, daher sollten Sie es nicht installieren müssen.

Hier wird der tie Aufruf bildet das Array @file zu Ihrer Textdatei, und splice ersetzt die vier Textzeilen mit dem Ersatz Inhalt von DATA lesen. Dann untie aktualisiert und schließt die Datei.

Beachten Sie, dass Sie myfile.txt auf den tatsächlichen Pfad zu Ihrer Eingabedatei ändern müssen.

use strict; 
use warnings 'all'; 

use Tie::File; 

tie my @file, 'Tie::File', 'myfile.txt' or die $!; 

splice @file, 152, 4, <DATA>; 

untie @file; 



__DATA__ 
     let view:String.UTF8View = string.utf8 

     if let from = range.lowerBound.samePosition(in: view), 
      let to = range.upperBound.samePosition(in: view) { 
      offset.pointee += Int32(string[string.startIndex..<range.lowerBound].utf8.count) 
      length.pointee = Int32(view.distance(from: from, to: to)) 
      return token 
     } else { 
      return nil 
     } 
1

A Perl one-liner, Linien zu ändern 153..156 in file mit Gehalten von repl.file, in-place

perl -i -wpe' 
    if (153..155) { s/.*\n// } 
    elsif ($.==156) { local $/; open $fh, "repl.file"; $_ = <$fh> };  
' file 

(Or $_ = path($file_name)->slurp mit Path::Tiny.)

Dies führt direkt in eine Skript, entweder durch das Schreiben einer neuen Datei mit Änderungen und das Verschieben über das Original (siehe in perlfaq5 und SO-Posts) oder vielleicht durch using -i ($^I) innerhalb eines Skripts.

+1

Wenn es ein One-Liner ist, warum ist es nicht alles auf einer Linie. – user3439894

+1

@ user3439894 Der Begriff "einzeilig" steht für etwas, das direkt von der Befehlszeile ausgeführt werden kann; es muss nicht in einer langen Zeile dargestellt werden, und es ist oft nicht (für die Lesbarkeit). Moderne Shells erlauben auch mehrzeilige Eingabe. Dies wurde in einer (langen) Zeile geschrieben und getestet. – zdim

+0

@ user3439894 Es ist auch ein nützliches Gerät, um eine rohe Version von Code zu testen. Wenn es befriedigt, dann kann man ein richtiges Skript schreiben, mit Fehlerprüfungen, Optionen, aufwendigerer Verarbeitung usw. So ist es hier gemeint. – zdim

Verwandte Themen