How to search and replace multiple lines with multiple lines

I looked at other answers regarding search and replace, but I just can't understand the patterns.

How can I change this part of the file (lines 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 

and replace it with the lines below?

  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 } 
+5
source share
5 answers

This may work for you (GNU sed and Bash):

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

or for most seds:

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

or if you prefer:

 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 

NB The first \ saves the leading space and each line, except for the last, which should be added with \ . Markdown in SO is not formatted properly when an empty string is represented by one \ (so I deleted the second replacement string), but most shells should.

+4
source

If you don't have the GNU-sed answer for @karafka and just want to change lines with exact line numbers, you can also use ed .

 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 
+2
source

sed is probably the best tool for this,

provided that your replacement text is in the replace.txt file

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

can only work for GNU sed

+1
source

This is a very good example for applying Tie::File module , which maps an array to lines of a text file so that any changes you make to the array will be displayed in the disk file. This is the main module, so you do not need to install it.

Here the tie call maps the @file array to your text file and splice replaces the four lines of text with the replacement content read from DATA . untie then updates and closes the file.

Note that you must change myfile.txt to the real path to your input file.

 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
source

Perl one-liner to change lines 153..156 to file with contents of 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 with Path :: Tiny .)

This is directly converted to a script, either by writing a new file with the changes, or moving it over the original (see perlfaq5 and SO), or perhaps using -i ( $^I ) within the script.

+1
source

Source: https://habr.com/ru/post/1273816/


All Articles