File1
zawartość:
line1-file1 "1"
line2-file1 "2"
line3-file1 "3"
line4-file1 "4"
File2
zawartość:
line1-file2 "25"
line2-file2 "24"
Pointer-file2 "23"
line4-file2 "22"
line5-file2 "21"
Po wykonaniu skryptu perl / shell File2
treść powinna stać się:
line1-file2 "25"
line2-file2 "24"
line1-file1 "1"
line2-file1 "2"
line3-file1 "3"
line4-file1 "4"
Pointer-file2 "23"
line4-file2 "22"
line5-file2 "21"
tzn wkleić zawartość File1
w File2
przed linią, która zawiera „pointer”.
text-processing
awk
sed
perl
użytkownik1228191
źródło
źródło
Odpowiedzi:
sed
ma do tego funkcję i może dokonać modyfikacji bezpośrednio:Ale to powoduje umieszczenie linii wskaźnika nad plikiem 1. Aby umieścić to poniżej, opóźnij wyjście liniowe:
źródło
-e 1x -e '2,${x;p}' -e '${x;p}'
robisz? Rozumiem, że wymieniasz rzeczy w buforze wzorów, a następnie drukujesz, ale nie wiem, co i dlaczego dodałeś opcję cichą-n
na początku.Bez użycia
sed
lubawk
...Najpierw znajdź linię, na której znajduje się wzór:
Następnie użyj 3 poleceń, aby uzyskać pożądany wynik:
Ma to tę wadę, że dostęp do plików 3 razy
file2
, ale może być wyraźniejszy niżsed
wawk
roztworze.źródło
awk
czyni to dość łatwym.Wstaw linię przed plikiem:
Aby wydrukować wewnętrzny plik po
Pointer
wierszu, wystarczy zmienić kolejność wzorców (musisz dodać średnik, aby uzyskać domyślną akcję) i możesz upuścićline
zmienną:I tylko dlatego, że nikt
perl
jeszcze nie używał ,źródło
system("cat innerfile")
wysyłainnerfile
do konsoli. Czy coś brakuje?Łatwa praca dla
ed
:-r file1
wczytuje podany plik za adresowaną linią, która w tym przypadku jest linią poprzedzającą dopasowanie pierwszej liniiPointer
. To wstawi zawartośćfile2
tylko raz, nawet jeśliPointer
występuje w wielu liniach. Jeśli chcesz wstawić go przed każdą pasującą linią, dodajg
flagę lobal:Wymień
,p
sięw
jeśli chcesz edytować plik w miejscu.Zaakceptowana
sed
odpowiedź działa w większości przypadków, ale jeśli znacznik znajduje się w ostatnim wierszu, polecenie nie będzie działać zgodnie z oczekiwaniami: wstawi zawartośćFile1
po znaczniku.Początkowo próbowałem z:
co również działa dobrze (podobnie jak
r
magia na końcu cyklu), ale ma ten sam problem, jeśli znacznik znajduje się na ostatniej linii (nie maN
linii zewnętrznej po ostatniej linii). Aby obejść ten problem, możesz dodać nowy wiersz do swoich danych wejściowych:Spowoduje to wstawienie
file2
treści przed każdą pasującą linią. Aby wstawić go tylko przed pierwszą pasującą linią, możesz użyćl
oop i po prostu przeciągnijn
linię ext, aż dojdziesz do końca pliku:Dzięki tym
sed
rozwiązaniom tracisz możliwość edycji w miejscu (ale możesz przekierować do innego pliku).źródło
Użyj pętli, aby odczytać linie w pliku 2. Jeśli znajdziesz linię zaczynającą się od
Pointer
, wydrukuj plik 1. Jest to pokazane poniżej:źródło
Jest kilka sposobów na obejście tego w /
sed
. Jednym ze sposobów jest opóźniony odczyt, zgodnie z zaleceniami przyjętej odpowiedzi. Można to również napisać w następujący sposób:... z nieco wyraźnym spoglądaniem w przyszłość zamiast z tyłu zaimplementowanym gdzie indziej z buforem wstrzymania. Które będą mieć ten sam problem z ostatniej linii, która @don_crissti zauważa jednak, bo
N
robi przyrost cykl linii ir
polecenia EAD jest stosowany przez numer linii.Możesz obejść to:
Nie wszystkie
sed
s zinterpretują-
standardowe wejście, ale wielu tak. ( POSIX mówi, żesed
powinien obsługiwać-
standard-in, jeśli implementator chce-
oznaczać standard-in ???)Innym sposobem jest uporządkowanie dołączonej zawartości w kolejności. Istnieje inne polecenie, które planuje wyjście w taki sam sposób, jak
r
robi to ead, ised
zastosuje je ir
ead w kolejności, w jakiej są skrypty. Jest jednak trochę bardziej zaangażowany - wymaga użycia jednego,sed
abya
dopasowaćPointer
dopasowanie do wyniku innegosed
w swoim skrypcie.Zasadniczo pierwszy
sed
pisze drugised
skrypt, który drugised
odczytuje na standardowym wejściu (może ...) i stosuje z kolei. Pierwszysed
działa tylko przy pierwszym dopasowaniu dlaPointer
znalezionego, a następnieq
wprowadza dane wejściowe. Jego zadaniem jest ...s/[]^$&\./*[]/\\&/g;H
sed
będzie musiał zinterpretować każdy fragment, który czyta dosłownie, aby go poprawnie. Gdy to zrobisz, umieść kopię wH
starej przestrzeni.s|.*|/&/!p;//!d|p; x
sed
abyp
zrewidował każdą linię wprowadzania,!
ale tę,/&/
którą właśnie zabezpiecziliśmy; a następnied
usunąć to samo.p
zrewiduj polecenia po drugimsed
, a następniex
zmieńh
stary i bufor buforów wzorców, aby działały na naszej zapisanej kopii.s|.|r file1&a\\&|p;q
\n
ewline, ponieważsed
będzie poprzedzał jeden, gdy staraliśmy sięH
o linię wcześniej. Więc wstawiamy polecenier file1
i podążamy za nim z naszą\n
ewline, a następnie poleceniea\\
dlaa
ppend, a następnie także\n
ewline. Cała reszta naszejH
linii eld jest zgodna z ostatnią\n
linią ewline.Skrypt, który pierwszy pisze, wygląda mniej więcej tak:
Zasadniczo drugi
sed
wypisze każdą linię, ale ten pierwszysed
ustawi ją naa
ppend. Dla tej konkretnej linii zaplanowano dwa opóźnione zapisy do standardowego wyjścia - pierwszy to ead, a drugi to kopia linii, którą chcemy po nim. Pierwsze doktorowanie nie jest nawet konieczne w tym przypadku (patrz? Żadnych odwrotnych ukośników), ale ważne jest, aby bezpiecznie uciec w sposób, w jaki tu robię, za każdym razem, gdy dopasowanie wzorca zostanie zmienione jako wejście.r
file1
sed
W każdym razie, więc ... jest kilka sposobów.
źródło
W AWK jest to dość proste:
Plik1 do pliku2 przed wzorcem = „Wskaźnik”
Najpierw załaduj zawartość pliku File1 do zmiennej
następnie włóż
(Lub, jeśli chcesz wstawić File1 po „Pointer”)
źródło
mój preferowany sposób: szablony .
Spowoduje to zastąpienie każdego changeme wystąpienie w origfile z treścią file2insert . Usuń ostatnią g z sed, aby zastąpić tylko pierwsze wystąpienie ZMIANY .
źródło
$x
z pierwszego polecenia, jeśli jest ono zdefiniowane tylko w drugim poleceniu?[Wstaw zawartość pliku do innego pliku PRZED wzorcem]
[Po wzorze]
źródło
N
działa ładnie, ale nie, jeśli WZORZEC pasuje do ostatniego wiersza wejściaźródło