Ich möchte mithilfe eines Shell-Skripts mehrere Zeilen in eine Datei einfügen. Betrachten wir den Inhalt meiner Eingabedatei als: input.txt:
abcd
accd
cdef
line
web
Jetzt muss ich vier Zeilen nach der Zeile 'cdef' in die Datei input.txt einfügen . Nach dem Einfügen sollte sich meine Datei folgendermaßen ändern:
abcd
accd
cdef
line1
line2
line3
line4
line
web
Die obige Einfügung sollte ich mit dem Shell-Skript machen. Kann mir jemand helfen?
r
Befehl zum Lesen zu verwenden/dev/stdin
.add.txt
?Verwenden von GNU
sed
:sed "/cdef/aline1\nline2\nline3\nline4" input.txt
Wenn Sie angefangen haben mit:
dies würde produzieren:
Wenn Sie die Änderungen an der Datei direkt speichern möchten, sagen Sie:
sed -i "/cdef/aline1\nline2\nline3\nline4" input.txt
quelle
sed
aber wow, ich bin verliebt in seine Kraft! Wenn Sie zuerst eine leere neue Zeile anhängen möchten, müssen Sie das Backslash-Zeichen nach dem Befehl append wie folgt maskieren :sed "/cdef/a\\\nline1\nline2\nline3\nline4" input.txt
. Ich bin mir nicht sicher, warum es so funktioniert, wenn jemand das erklären könnte, wäre das schön!cdef
ein. Gibt es eine Möglichkeit, sie so zu gestalten, dass sie nur beim ersten Auftreten eingefügt wirdcdef
und nicht mehr?sed
implementiert dena
Befehl nicht genau wie GNUsed
, daher funktioniert das oben Gesagte unter MacOS ohne Mods nicht - zumindest ab MacOS 10.13 (siehe unix.stackexchange.com/a/131940/230763 )sed '/^cdef$/r'<( echo "line1" echo "line2" echo "line3" echo "line4" ) -i -- input.txt
quelle
sed '/^cdef$/r' <(printf "%s\n" line{1..4}) -i -- input.txt
.Verwenden von
awk
:awk '/cdef/{print $0 RS "line1" RS "line2" RS "line3" RS "line4";next}1' input.txt
Erläuterung:
/.../
print $0
RS
ist eine integrierteawk
Variable, die standardmäßig auf eingestellt istnew-line
.1
Am Ende werden alle anderen Zeilen gedruckt. Wenn Sie "next
Vorher verwenden" verwenden, können wir die aktuelle Zeile verhindern, da Sie sie bereits mit verwendet habenprint $0
.$ awk '/cdef/{print $0 RS "line1" RS "line2" RS "line3" RS "line4";next}1' input.txt abcd accd cdef line1 line2 line3 line4 line web
So nehmen Sie Änderungen an der Datei vor:
awk '...' input.txt > tmp && mv tmp input.txt
quelle
Diese Antwort ist leicht zu verstehen
Ersetzen Sie die Originaldatei
FILENAME = 'app / Providers / AuthServiceProvider.php'
SCHRITT 1 Kopie bis zum Muster
sed '/THEPATTERNYOUARELOOKINGFOR/Q' $FILENAME >>${FILENAME}_temp
SCHRITT 2 Fügen Sie Ihre Zeilen hinzu
cat << 'EOL' >> ${FILENAME}_temp HERE YOU COPY AND PASTE MULTIPLE LINES, ALSO YOU CAN //WRITE COMMENTS AND NEW LINES AND SPECIAL CHARS LIKE $THISONE EOL
SCHRITT 3 Fügen Sie den Rest der Datei hinzu
grep -A 9999 'THEPATTERNYOUARELOOKINGFOR' $FILENAME >>${FILENAME}_temp
Ersetzen Sie die Originaldatei
mv ${FILENAME}_temp $FILENAME
Wenn Sie Variablen benötigen, ersetzen Sie in Schritt 2 'EOL' durch EOL
cat << EOL >> ${FILENAME}_temp this variable will expand: $variable1 EOL
quelle
Hier ist eine generische Lösung auf @rindeal basierte Lösung , die auf MacOS / BSD nicht funktioniert (
/r
erwartet eine Datei):$ cat << EOF | sed '/^cdef$/ r /dev/stdin' input.txt line 1 line 2 EOF # outputs: abc cdef line 1 line 2 line
Dies kann verwendet werden, um an der angegebenen Position etwas in die Datei zu leiten:
$ date | sed '/^cdef$/ r /dev/stdin' input.txt # outputs abc cdef Tue Mar 17 10:50:15 CET 2020 line
Sie können auch mehrere Befehle hinzufügen, um die Markierungszeile zu löschen
cdef
:$ date | sed '/^cdef$/ { r /dev/stdin d }' input.txt # outputs abc Tue Mar 17 10:53:53 CET 2020 line
quelle
Ich musste ein paar Dateien mit minimalem Werkzeugaufwand
sed -e '/../r file.txt
vorlegen, und für mich besteht das Problem oben darin, dass die Datei erst angehängt wird, nachdem der Rest des Spiels ausgedruckt wurde, und sie nicht ersetzt.Dies ist nicht der Fall (alle Übereinstimmungen werden ersetzt und die Musterübereinstimmung wird an derselben Stelle fortgesetzt).
#!/bin/bash TEMPDIR=$(mktemp -d "${TMPDIR:-/tmp/}$(basename $0).XXXXXXXXXXXX") # remove on exit trap "rm -rf $TEMPDIR" EXIT DCTEMPLATE=$TEMPDIR/dctemplate.txt DCTEMPFILE=$TEMPDIR/dctempfile.txt # template that will replace printf "0replacement 1${SHELL} data 2anotherlinenoEOL" > $DCTEMPLATE # test data echo -e "xxy \n987 \nxx xx\n yz yxxyy" > $DCTEMPFILE # print original for debug echo "---8<--- $DCTEMPFILE" cat $DCTEMPFILE echo "---8<--- $DCTEMPLATE" cat $DCTEMPLATE echo "---8<---" # replace 'xx' -> contents of $DCTEMPFILE perl -e "our \$fname = '${DCTEMPLATE}';" -pe 's/xx/`cat $fname`/eg' ${DCTEMPFILE}
quelle
Sie können
awk
zum Einfügen der Ausgabe eines Befehls in der Mitte von verwendeninput.txt
.Die Zeilen eingefügt werden können den Ausgang eines sein
cat otherfile
,ls -l
oder 4 Zeilen mit einer Anzahl von erzeugtenprintf
.awk 'NR==FNR {a[NR]=$0;next} {print} /cdef/ {for (i=1; i <= length(a); i++) { print a[i] }}' <(printf "%s\n" line{1..4}) input.txt
quelle