2017-12-02 290 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