2017-12-02 291 views
5

我查看了有关搜索和替换的其他答案,但我无法理解这些模式。如何用多行搜索和替换多行

我怎样才能更改文件的这一部分(行号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 

和替换它用下面几行?

 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

数字153-156是输入文件的一部分吗?或者你只是在这里展示他们的插图? – PerlDuck

+0

只是显示他们的插图 – sirvon

+0

您是否需要严格取代153..156行,或您显示的代码(可能或不可能在这些行上)? – zdim

回答

4

这可能会为你工作(GNU sed的&击):

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

或者对于大多数SEDS:

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

或者如果你喜欢:

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 

注:第一个\保留领先空间和每一行,除了最后需要附加\。当一个空行由一个单独的\(所以我删除了替换的第二行)表示空行时,SO中的降价格式不正确,但大多数shell应该。

1

sed可能是这种情况的最佳工具,

假设您的替换文本是在文件replace.txt

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

可能只工作了GNU sed

2

如果您对于@ karafka的回答没有GNU-sed,只想在确切的行号处更改行,您也可以使用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 
1

这是Tie::File module的应用程序,它映射数组到一个文本文件中的线,所以您对数组的任何更改将在磁盘文件中反映出来一个很好的案例。这是一个核心模块,所以你不需要安装它。

这里,tie调用数组@file映射到你的文本文件,并 splice用从DATA阅读更换内容的四行文字。 然后untie更新并关闭文件。

请注意,您必须将myfile.txt更改为输入文件的真实路径。

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

一个Perl的一行,以改变线153..156filerepl.file内容,就地

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

(或者$_ = path($file_name)->slurpPath::Tiny。)

这直接转换成一个脚本,可以通过写入一个包含更改的新文件并将其移至原始文件(请参阅in perlfaq5和SO帖子),或者在脚本中将其移至using -i ($^I)

+1

如果是单线,为什么不是全部在一条线上。 – user3439894

+1

@ user3439894术语“单线”代表可直接从命令行执行的某些内容;它不必在一条长线上呈现,而且它通常不是(为了可读性)。此外,现代外壳允许多线输入。这是写在一个(长)线测试。 – zdim

+0

@ user3439894这也是测试原始版本代码的有用工具。如果满足,那么可以编写一个合适的脚本,包括错误检查,选项,更精细的处理等。这就是它的目的。 – zdim