2017-04-14 7 views
1

Mit sed, ich versuche, das erste Auftreten eines Kommentars in einem Skript zu ersetzen, wie:Sed/Awk: Ersetzen Sie das erste Vorkommen eines Musters mit dem Inhalt einer anderen Datei

#ENTRYPOINT_CONTENT

durch den Inhalt einer zweiten Datei ($ file_content) in eine dritte Datei (/base.sh).

So, nach vielen Dokumentationen, sollte die Zeichenfolge ganz einfach sein, so etwas wie:

sed "s|\#ENTRYPOINT_CONTENT|$file_content|" /base.sh

Aber ich immer mit Fehlern wie am Ende:

sed: -e expression #1, char 23: unterminated s' command

oder ähnlich Nachrichten, auch verschiedene Trennzeichen versucht, auch mit Awk statt, aber ohne Erfolg, scheint es in Ordnung zu sein, nachdem die # in das Suchmuster, aber ich kann immer noch nicht den Inhalt der Datei als Variable erhalten le in Sed.

Irgendwelche Ideen, entweder mit Sed oder Awk?

Edit: --------------------

@Sundeep @James Brown:

Ich will nicht die Themen mischen noch zu lang sein :) die Antwort auf Sie Klarstellung Anfrage ist am Ende dieser Bearbeitung in Fettdruck, aber nur um den Kontext zu erarbeiten, ist mein Fall ein Docker Einstiegspunkt Skript in Bash (für eine Basis Docker Bild) /root/test/Basis :

#!/usr/bin/env bash 

#ENTRYPOINT_CONTENT 

if [[ -e "/root/test/custom" ]]; then 

    printf "\n\n#ENTRYPOINT_CONTENT\n" >> /root/test/custom 

    # Code from whjm's reply below (actually works but appends shebangs from custom files) 
    sed -e '0,/^#ENTRYPOINT_CONTENT/!b; /^#ENTRYPOINT_CONTENT/{ r /root/test/custom' -e 'd; }' /root/test/base.sh >> /root/test/base2.sh 

    mv /root/test/base2.sh /root/test/base.sh 
    rm -f /root/test/custom 

fi 

Ich mag nur Benutzer einen anderen Bash-Skript ihrer eigenen auf einem bestimmten Pfad fallen lassen (etwa /root/test/individuelle), zum Beispiel:

#!/usr/bin/env bash 
echo 'My 2nd bash code' 

Das erste Skript oben (Basis) soll den Inhalt einfügen dies der benutzerdefinierten Datei auf #ENTRYPOINT_CONTENT Position (in der Basis Skript selbst, ohne diese Suchzeichenfolge zu entfernen), wie:

#!/usr/bin/env bash 

echo 'My 2nd bash code' 

#ENTRYPOINT_CONTENT 

if [[ -e "/root/test/custom" ]]; then 

    printf "\n\n#ENTRYPOINT_CONTENT\n" >> /root/test/custom 

    # Code from whjm's reply below 
    sed -e '0,/^#ENTRYPOINT_CONTENT/!b; /^#ENTRYPOINT_CONTENT/{ r /root/test/custom' -e 'd; }' /root/test/base.sh >> /root/test/base2.sh 

    mv /root/test/base2.sh /root/test/base.sh 
    rm -f /root/test/custom 

fi 

Wenn ein anderer Benutzer später fällt ano ther benutzerdefinierte Skript auf dem gleichen Weg, sollten wir den Code dieses dritten benutzerdefinierten Skript wie folgt angehängt:

#!/usr/bin/env bash 
echo 'My 2nd bash code' 
echo 'My 3rd bash code' 
#ENTRYPOINT_CONTENT 

if [[ -e "/root/test/custom" ]]; then 
# ... and so on 

In Bezug auf die Bauden von benutzerdefinierten Dateien, es ist nicht ein echtes Problem, wenn sie zu der Basisdatei angehängt werden, Der sed-Code von @whjm funktioniert wie erwartet, hängt aber an sie an, während (überraschenderweise) beide awk-Codes von @James Brown bereits (und anmutig :) alle zusätzlichen shebangs von benutzerdefinierten Dateien ignorieren (wahrscheinlich weil sie auch mit # als #ENTRYPOINT_CONTENT-Suche beginnen) string) aber derzeit zum Teil preprend den Code wie:

#!/usr/bin/env bash 
echo 'My 3rd bash code' 
echo 'My 2nd bash code' 
#ENTRYPOINT_CONTENT 

während ich versuche, es zu erhalten hängten wie:

#!/usr/bin/env bash 
echo 'My 2nd bash code' 
echo 'My 3rd bash code' 
#ENTRYPOINT_CONTENT 

Also, kurz gesagt, @Sundeep, wenn Sie mir nur eine aktualisierte Version Ihres awk-Code für diese geben könnte, wäre es perfekt ! : D (konnte keinen Weg finden, dies zu invertieren ...) Vielen Dank.

-Code aus dem vorherigen Beitrag:

NR==FNR { b=b (FNR==1?"":ORS) $0; next } 
{ r=r (FNR==1?"":ORS) $0 } #ENTRYPOINT_CONTENT 
END { sub(/\#[^\n]+/,r,b); print b} 
+0

Sie Fehler erhalten, wenn '$ file_content' Zeilenumbrüche hat, die' | 'Zeichen , etc ... wenn Sie einen kleinen zusammengesetzten Inhalt von 'base.sh' und' file_content' hinzufügen können, wird es Ihnen helfen, eine Lösung zu schaffen ... vor allem erstellen Sie ein Beispiel mit mehreren '# ENTRYPOINT_CONTENT' und zeigen Sie das erwartete Ausgabe – Sundeep

+0

@Sundeep: meine Antwort auf die Bearbeitung oben – glc

Antwort

0

Wenn Sie mit GNU sed:

[STEP 101] # cat file1 
11 
xx // replace me 
44 
xx // don't replace me 
55 
[STEP 102] # cat file2 
22 
33 
[STEP 103] # sed -e '0,/^xx/!b; /^xx/{ r file2' -e 'd }' file1 
11 
22 
33 
44 
xx // don't replace me 
55 
[STEP 104] # 
+0

Funktioniert gut! Danke vielmals ! Für andere Leser ist 'xx' im obigen Code die Zeichenfolge, die gesucht und ersetzt werden soll (' # ENTRYPOINT_CONTENT' in meinem Fall) – glc

Verwandte Themen