Fügen Sie mit sed oder awk eine Zeile an einer bestimmten Zeilennummer ein

146

Ich habe eine Skriptdatei, die ich mit einem anderen Skript ändern muss, um einen Text in die 8. Zeile einzufügen.

Zu fügender String : Project_Name=sowstest, in eine Datei mit dem Namen start.

Ich habe versucht, awk und sed zu verwenden, aber mein Befehl wird verstümmelt.

Ashok
quelle

Antworten:

231
sed -i '8i8 This is Line 8' FILE

Einfügungen in Zeile 8

8 This is Line 8

in Datei DATEI

-i führt die Änderung direkt in die Datei FILE durch, keine Ausgabe in stdout, wie in den Kommentaren von Glenn Jackman erwähnt.

Benutzer unbekannt
quelle
3
Ja, der Schalter -i ist spezifisch für GNU-sed.
Benutzer unbekannt
1
Nein. -I bedeutet "Ändern Sie die angegebene Datei an Ort und Stelle". Einfügen vs. Anhängen wird mit '8isomething' vs. '8asomething' erreicht, unabhängig vom -i-Schalter.
Benutzer unbekannt
11
Mac-Benutzer: mit Homebrew, brew install gnu-sedund verwenden Sie diese mitgsed
cwd
4
Das ist super nützlich! Kann ich am Anfang der Zeile Leerzeichen einfügen? Ich bemerkte, dass sed nicht auf anfängliche Leerzeichen
achtet
9
@elju: Ja, maskiere es mit einem Backslash : sed '8i\ 8 This is Line 8' FILE.
Benutzer unbekannt
32

Eine edAntwort

ed file << END
8i
Project_Name=sowstest
.
w
q
END

.auf seiner eigenen Leitung endet der Eingabemodus; wschreibt; qquitt. GNU ed hat einen wqBefehl zum Speichern und Beenden, alte Eds jedoch nicht.

Weitere Informationen: https://gnu.org/software/ed/manual/ed_manual.html

Glenn Jackman
quelle
19

OS X / macOS / FreeBSD sed

Das -iFlag funktioniert unter macOS anders sedals in GNU sed.

So verwenden Sie es unter macOS / OS X:

sed -i '' '8i\
8 This is Line 8' FILE

Siehe man 1 sedfür weitere Informationen.

Mateusz Piotrowski
quelle
18

die awk antwort

awk -v n=8 -v s="Project_Name=sowstest" 'NR == n {print s} {print}' file > file.new
Glenn Jackman
quelle
@glenn jackman Ich muss #define SERVER@"http://10.35.42.54/ms0.8"eine bestimmte Zeile eingeben . Wie kann ich das erreichen?
Nevin Raj Victor
1
Ich denke, Nevin muss nur den Anführungszeichen in seiner Zeichenfolge mit Backslashes entkommen
Chris Koknat
@waLLe, beginne mit der awk-Infoseite, die eine schöne Beschreibung der Funktionsweise von awk enthält. Hier habe ich 2 "Bedingung {Aktion}" Paare, die zweite hat keine Bedingung, was bedeutet, dass die Aktion für jeden Datensatz ausgeführt wird. Nachdem Sie mit dem Lesen fertig sind und noch Fragen haben, lassen Sie es mich wissen.
Glenn Jackman
@glennjackman fast da .. habe das einfach nicht bekommen: file> file.new
w411 3
"Datei" steht für den Namen der Datei, an der awk arbeitet. >ist das Shell- Umleitungssymbol, damit die Ausgabe von awk in der Datei "file.new" gespeichert wird.
Glenn Jackman
16

Auf POSIX sed(und zum Beispiel auf OS X sed, siehe sedunten) müssen iein Backslash und ein Zeilenumbruch folgen. Zumindest OS X sedenthält nach dem eingefügten Text keine neue Zeile:

$ seq 3|gsed '2i1.5'
1
1.5
2
3
$ seq 3|sed '2i1.5'
sed: 1: "2i1.5": command i expects \ followed by text
$ seq 3|sed $'2i\\\n1.5'
1
1.52
3
$ seq 3|sed $'2i\\\n1.5\n'
1
1.5
2
3

Um eine Zeile zu ersetzen, können Sie die Befehle c(Ändern) oder s(Ersetzen) mit einer numerischen Adresse verwenden:

$ seq 3|sed $'2c\\\n1.5\n'
1
1.5
3
$ seq 3|gsed '2c1.5'
1
1.5
3
$ seq 3|sed '2s/.*/1.5/'
1
1.5
3

Alternativen mit awk:

$ seq 3|awk 'NR==2{print 1.5}1'
1
1.5
2
3
$ seq 3|awk '{print NR==2?1.5:$0}'
1
1.5
3

awkinterpretiert Backslashes in Variablen, die mit übergeben wurden, -vaber nicht in Variablen, die übergeben wurden mit ENVIRON:

$ seq 3|awk -v v='a\ba' '{print NR==2?v:$0}'
1
a
3
$ seq 3|v='a\ba' awk '{print NR==2?ENVIRON["v"]:$0}'
1
a\ba
3

Beide ENVIRONund -vwerden von POSIX definiert.

Lri
quelle
7

Perl-Lösungen:

schnell und dreckig:

perl -lpe 'print "Project_Name=sowstest" if $. == 8' file

  • -l entfernt Zeilenumbrüche und fügt sie wieder hinzu, sodass "\ n" nicht mehr benötigt wird.
  • -p Durchläuft die Eingabedatei und druckt jede Zeile
  • -e führt den Code in einfachen Anführungszeichen aus

$. ist die Zeilennummer

Entspricht der awk-Lösung von @ glenn mit benannten Argumenten:

perl -slpe 'print $s if $. == $n' -- -n=8 -s="Project_Name=sowstest" file

  • -s aktiviert einen rudimentären Argumentparser
  • -- verhindert, dass -n und -s vom Standard-Perl-Argument-Parser analysiert werden

Positionsbefehlsargumente:

perl -lpe 'BEGIN{$n=shift; $s=shift}; print $s if $. == $n' 8 "Project_Name=sowstest" file

Umgebungsvariablen:

setenv n 8 ; setenv s "Project_Name=sowstest"
echo $n ; echo $s
perl -slpe 'print $ENV{s} if $. == $ENV{n}' file

ENV ist der Hash, der alle Umgebungsvariablen enthält

Getopt, um Argumente in Hash% o zu analysieren:

perl -MGetopt::Std -lpe 'BEGIN{getopt("ns",\%o)}; print $o{s} if $. == $o{n}' -- -n 8 -s "Project_Name=sowstest" file

Getopt :: Lange und längere Optionsnamen

perl -MGetopt::Long -lpe 'BEGIN{GetOptions(\%o,"line=i","string=s")}; print $o{string} if $. == $o{line}' -- --line 8 --string "Project_Name=sowstest" file

Getopt ist die empfohlene Standardbibliothekslösung.
Dies kann für einzeilige Perl-Skripte übertrieben sein, kann aber durchgeführt werden

Chris Koknat
quelle
2
Ein großes Lob an dich Chris, dass du dir die Zeit genommen hast, das alles zu erklären und es so schön zu gestalten, aber wow, deshalb mag ich Perl nicht.
rsaw
5

Für diejenigen, die unter SunOS arbeiten, das kein GNU ist, hilft der folgende Code:

sed '1i\^J
line to add' test.dat > tmp.dat
  • ^ J wird mit ^ V + ^ J eingefügt
  • Fügen Sie die neue Zeile nach '1i hinzu.
  • \ MUSS das letzte Zeichen der Zeile sein.
  • Der zweite Teil des Befehls muss sich in einer zweiten Zeile befinden.
Nasri Najib
quelle
5

sed -e '8iProject_Name=sowstest' -i start mit GNU sed

Probelauf:

[root@node23 ~]# for ((i=1; i<=10; i++)); do echo "Line #$i"; done > a_file
[root@node23 ~]# cat a_file
Line #1
Line #2
Line #3
Line #4
Line #5
Line #6
Line #7
Line #8
Line #9
Line #10
[root@node23 ~]# sed -e '3ixxx inserted line xxx' -i a_file 
[root@node23 ~]# cat -An a_file 
     1  Line #1$
     2  Line #2$
     3  xxx inserted line xxx$
     4  Line #3$
     5  Line #4$
     6  Line #5$
     7  Line #6$
     8  Line #7$
     9  Line #8$
    10  Line #9$
    11  Line #10$
[root@node23 ~]# 
[root@node23 ~]# sed -e '5ixxx (inserted) "line" xxx' -i a_file
[root@node23 ~]# cat -n a_file 
     1  Line #1
     2  Line #2
     3  xxx inserted line xxx
     4  Line #3
     5  xxx (inserted) "line" xxx
     6  Line #4
     7  Line #5
     8  Line #6
     9  Line #7
    10  Line #8
    11  Line #9
    12  Line #10
[root@node23 ~]# 
jno
quelle
Woher kommt das Trailing $in Zeile 3 nach dem Einfügen?
JWW
Es ist von der -AFlagge bis cat:)
jno
Was ist, wenn die Zeichenfolge, die Sie einfügen möchten, Anführungszeichen, Klammern usw. enthält?
Anentropic
Siehe Aktualisierung des obigen Textes. Das heißt, Sie müssen diesen Zeichen entsprechend entkommen.
jno
0

sed -i "" -e $ '4 a \\ n''Project_Name = sowstest' start

  • Diese Zeile funktioniert gut unter macOS
Elza James
quelle