Insert text before a specific line using Bash

How can I insert a rowset (about 5) into a file in the first place , is a row found?

For instance:

BestAnimals.txt

dog cat dolphin cat 

$ "Insert a giraffe in BestAnimals.txt in front of a cat"> NewBestAnimals.txt

NewBestAnimals.txt

 dog giraffe cat dolphin cat 
+4
source share
5 answers

If you are using gnu sed:

 $ cat animals dog cat dolphin cat $ sed "/cat/ { N; s/cat\n/giraffe\n&/ }" animals dog giraffe cat dolphin cat 
  • matches the line with (/ cat /)
  • continue on the next line (N)
  • replace the matched pattern with the insert and the matched string, where & represents the matched string.
+9
source

If you know (or somehow find out) the line:

 sed -n '/cat/=' BestAnimals.txt 

You can use sed:

 sed -i '2i giraffe' BestAnimals.txt 
+2
source

Awk solution:

 awk '/cat/ && c == 0 {c = 1; print "giraffe"}; {print}' \ BestAnimals.txt 

If the animals you want to insert are in "MyOtherBestAnimals.txt", you can also do

 awk '/cat/ && c == 0 {c = 1; system("cat MyOtherBestAnimals.txt") }; {print} ' \ BestAnimals.txt 

This answer can in principle be broken down as follows, since ; splits awk condition pairs:

  • /cat/ && c == 0 { c = 1; ... } /cat/ && c == 0 { c = 1; ... } sets c to 1 in the first line containing cat. Then the commands placed in ... are executed, but only once, since c now equal to 1.
  • {print} - print an action without a condition: prints any input line. This is done after the specified pair of conditions of action.

Depending on what is actually on ... , a giraffe is printed, or the contents of "MyOtherBestAnimals.txt" are sent to standard output before printing the first line containing "cat".

Edit

After analyzing the @glenn jackman solution, it seems that this solution can still be improved: when using the input file

 nyan cat cat 

data is appended to nyan cat , not to a line equal to cat . Then, the solution should query the full string equal to cat :

 awk '$0 == "cat" && c == 0 {c = 1; print "giraffe"}; {print}' \ BestAnimals.txt 

to insert one row and

 awk '$0 == "cat" && c == 0 {c = 1; system("cat MyOtherBestAnimals.txt") }; {print} ' \ BestAnimals.txt 

to insert a file

+2
source
 awk -v insert=giraffe -v before=cat ' $1 == before && ! inserted { print insert inserted++ } {print} ' BestAnimals.txt > NewBestAnimals.txt 
+2
source

I'd:

  • Use grep to find the line number of the first match
  • Use head to get text preceding a match.
  • Insert new content with cat
  • Use tail to get lines after match

It is not fast, efficient and not elegant. But this is pretty straight forward, and if the file is not gigantic and / or you need to do it many times per second, everything should be fine.

+1
source

Source: https://habr.com/ru/post/1432091/


All Articles