Jak zamienić część pliku tekstowego między znacznikami na inny plik tekstowy?


26

Powiedzmy, że mam taki plik tekstowy:

# custom content section
a
b

### BEGIN GENERATED CONTENT
c
d
### END GENERATED CONTENT

Chciałbym zastąpić część między GENERATED CONTENTtagami zawartością innego pliku.

Jaki jest najprostszy sposób to zrobić?

Odpowiedzi:


36
lead='^### BEGIN GENERATED CONTENT$'
tail='^### END GENERATED CONTENT$'
sed -e "/$lead/,/$tail/{ /$lead/{p; r insert_file
        }; /$tail/p; d }"  existing_file

Doskonały. sedmoże zrobić o wiele więcej niż tylko s/.../...!
DevSolar

Hmmm nie działa dla mnie, czy powinienem umieścić polecenie sed w jednym wierszu?
lzap

3
r insert_filePolecenie musi być ostatnią rzeczą, na swojej linii. Zauważ, że ani białe znaki, ani komentarze nie są dozwolone po nim. Kod został przetestowany przy użyciu GNU sedz --posixwłączoną opcją i działał zgodnie z oczekiwaniami, więc powinien działać z dowolną zgodną z POSIX-emsed .
Peter.O

1
Cholera, to spoko! To dzieje się w moim słowniku sed! Niezwykle przydatne i pięknie proste. Dziękuję Ci!
DanielSmedegaardBuus

2
Uwaga: edycja na miejscu wymaga przechwycenia danych wyjściowych sed (np. output=$(sed -e "..." existing_file)), A następnie wykonania zamiany w drugim przejściu (np. echo "$output" > existing_file), Ponieważ próba przekierowania do pliku, z którego czytasz, spowoduje obcięcie go przed odczytaniem zawartości.
Chris Tonkinson

5
newContent=`cat new_file`
perl -0777 -i -pe "s/(### BEGIN GENERATED CONTENT\\n).*(\\n### END GENERATED CONTENT)/\$1$newContent\$2/s" existing_file

Dobra robota. O wiele prostsze niż moje. :)
Dr Kitty

4

Ostrzeżenie: To zdecydowanie nie jest najprostszy sposób, aby to zrobić. (EDYCJA: bash działa; POSIX grep też jest w porządku)

Jeśli główny tekst znajduje się w pliku „main”, a wygenerowana treść znajduje się w pliku „gen”, możesz wykonać następujące czynności:

#!/bin/bash
BEGIN_GEN=$(cat main | grep -n '### BEGIN GENERATED CONTENT' | sed 's/\(.*\):.*/\1/g')
END_GEN=$(cat main | grep -n '### END GENERATED CONTENT' | sed 's/\(.*\):.*/\1/g')
cat <(head -n $(expr $BEGIN_GEN - 1) main) gen <(tail -n +$(expr $END_GEN + 1) main) >temp
mv temp main

czy to działa? Myślę, że twoja ostatnia linia otworzy się maindo pisania, wyczyszczenia, zanim zostanie przeczytana przez kota.
chepner

@chepner Crap, masz rację. Reszta jednak działa. Naprawię to.
Dr Kitty

3
ed -s FILE1 <<EOF
/### BEGIN GENERATED/+,/### END GENERATED/-d
/### BEGIN GENERATED/ r FILE2
w
q
EOF

Korzystanie z heredoc i edytora linii ed. Pierwszym wierszem w heredoc jest usunięcie „d” wiersza po „+” „### BEGIN GENERATED ...”, a wiersz przed „-” „### END GENERATED ...” w drugim wierszu wstawia PLIK 2 po wierszu ### END
GENERATED

przepraszam, co miałem na myśli, to wstawić PLIK2 po wierszu „### BEGIN
GENERATED

Uspokójcie się, to przecież mój pierwszy raz :-). Mogłem również użyć tego samego słowa, ale inne rozwiązanie nie używa heredoków, ale printf i potoku. W każdym razie przepraszam, jeśli popełniłem błąd :-)
Jetchisel

Dzięki, bardzo czytelne! Btw - zamiast tego r FILE2możesz powiedzieć, r !commandże czytasz z innego skryptu.
Kos
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.