2017-12-02 148 views
5

Przyjrzałem się innym odpowiedziom dotyczącym wyszukiwania i zamiany, ale po prostu nie mogę zrozumieć tych wzorców.Jak wyszukiwać i zamieniać wiele linii za pomocą wielu linii

Jak mogę zmienić tę część pliku (numery linii 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 

i zastąpić ją poniżej linii?

 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

Czy numery 153-156 są częścią pliku wejściowego? A może po prostu pokazałeś je tutaj w celach ilustracyjnych? – PerlDuck

+0

pokazywałam je po prostu dla ilustracji – sirvon

+0

Czy musisz zastąpić ściśle linie 153..156, czy też kod, który pokazałeś (który może, ale nie musi być na tych liniach)? – zdim

Odpowiedz

4

To może pracować dla Ciebie (GNU sed & Bash):

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

lub dla większości SEDS:

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

lub jeśli wolisz:

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 Pierwszy obiekt \ zachowuje początkową przestrzeń i każdą następującą linię, z wyjątkiem ostatniej, która musi być dołączona z \.Obniżka w SO nie jest formatowana poprawnie, gdy pusta linia jest reprezentowana przez pojedynczy \ (więc usunąłem drugą linię wymiany), ale większość powłok powinna.

1

sed jest prawdopodobnie najlepszym narzędziem do tego,

zakładając tekst wymiana jest w pliku replace.txt

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

można tylko pracować dla GNU sed

2

Jeśli nie mam GNU-sed dla odpowiedzi @ karafki i po prostu chcę zmienić wiersze na dokładne numery linii, możesz również użyć 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

Jest to bardzo dobra sprawa dla stosowania Tie::File module, który mapuje tablicę do linii w pliku tekstowym tak, że wszelkie zmiany wprowadzone do tablicy zostaną uwzględnione w pliku na dysku. Jest to moduł podstawowy, więc nie musisz go instalować.

Tutaj rozmowa tie odwzorowuje tablicę @file do pliku tekstowego, a splice zastępuje cztery wiersze tekstu z zawartością zamiennych odczytanych z DATA. Następnie untie aktualizuje i zamyka plik.

Pamiętaj, że musisz zmienić myfile.txt na prawdziwą ścieżkę do pliku wejściowego.

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 jedna wkładka, modyfikowanie linii 153..156 w file o zawartości repl.file w miejscu

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

(A $_ = path($file_name)->slurp z Path::Tiny).

ten przekłada się bezpośrednio na skrypt, albo wypisując nowy plik ze zmianami i przesuwając go nad oryginałem (patrz in perlfaq5 i posty SO), lub może przez using -i ($^I) w skrypcie.

+1

Jeśli jest to jedna liniówka, dlaczego nie wszystko jest w jednej linii. – user3439894

+1

@ user3439894 Termin "jednolinijkowy" oznacza coś, co można wykonać bezpośrednio z wiersza poleceń; nie musi być prezentowana w jednym długim wierszu i często nie jest (dla czytelności). Ponadto nowoczesne powłoki umożliwiają wprowadzanie wielu linii. Zostało to napisane i przetestowane w jednej (długiej) linii. – zdim

+0

@ user3439894 Jest to również przydatne urządzenie do testowania prostej wersji kodu. Jeśli to spełnia, można napisać odpowiedni skrypt, z kontrolami błędów, opcjami, bardziej skomplikowanym przetwarzaniem itd. Oto, w jaki sposób jest tutaj przeznaczony. – zdim