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.

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.


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


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.


18

die awk antwort

awk -v n=8 -v s="Project_Name=sowstest" 'NR == n {print s} {print}' file > file.new

@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.


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


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.

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 ~]# 

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.