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ć?

smokris
źródło

Odpowiedzi:

36
lead='^### BEGIN GENERATED CONTENT$'
tail='^### END GENERATED CONTENT$'
sed -e "/$lead/,/$tail/{ /$lead/{p; r insert_file
        }; /$tail/p; d }"  existing_file
Peter.O
źródło
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
smokris
źródło
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
Dr Kitty
źródło
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
Jetchisel
źródło
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