Reputation: 1647
I want to insert multiple lines into a file using shell script. Let us consider my input file contents are: input.txt:
abcd
accd
cdef
line
web
Now I have to insert four lines after the line 'cdef' in the input.txt file. After inserting my file should change like this:
abcd
accd
cdef
line1
line2
line3
line4
line
web
The above insertion I should do using the shell script. Can any one help me?
Upvotes: 102
Views: 164166
Reputation: 727
Putting the content over the 4th line (like you want)
sed -i "4i line1\nline2\nline3\nline4" input.txt
If you don't want to save the changes to the file in-place, remove "-i" :
sed "4i line1\nline2\nline3\nline4" input.txt
Using sed by GNU*
If you started input.txt with:
abcd
accd
cdef
line
web
this would produce:
abcd
accd
cdef
line1
line2
line3
line4
line
web
Upvotes: 0
Reputation: 449
Based on @rindeal solution but with better readability of the input
sed '/^cdef$/r'<(cat <<EOF
line1
line2
line3
line4
EOF
) -i -- input.txt
Upvotes: 2
Reputation: 924
suppose you have a file called 'insert.txt' containing the lines you want to add:
line1
line2
line3
line4
If the PATTERN 'cdef' REPEATS MULTIPLE TIMES in your input.txt file, and you want to add the lines from 'insert.txt' after ALL occurrences of the pattern 'cdef' , then a easy solution is:
sed -i -e '/cdef/r insert.txt' input.txt
but, if the PATTERN 'cdef' REPEATS MULTIPLE TIMES in your input.txt file, and you want to add the lines from 'insert.txt' ONLY AFTER THE FIRST OCCURRENCE of the pattern, a beautiful solution is:
printf "%s\n" "/cdef/r insert.txt" w | ed -s input.txt
Both solution will work fine in case the pattern happens only once in your input.txt file.
Upvotes: 0
Reputation: 76
if you want to do that with a bash script, that's useful.
echo $password | echo 'net.ipv4.ping_group_range=0 2147483647' | sudo -S tee -a /etc/sysctl.conf
Upvotes: -1
Reputation: 6547
Here is a more generic solution based on @rindeal solution which does not work on MacOS/BSD (/r
expects a file):
cat << DOC > input.txt
abc
cdef
line
DOC
$ cat << EOF | sed '/^cdef$/ r /dev/stdin' input.txt
line 1
line 2
EOF
# outputs:
abc
cdef
line 1
line 2
line
This can be used to pipe anything into the file at the given position:
$ date | sed '/^cdef$/ r /dev/stdin' input.txt
# outputs
abc
cdef
Tue Mar 17 10:50:15 CET 2020
line
Also, you could add multiple commands which allows deleting the marker line cdef
:
$ date | sed '/^cdef$/ {
r /dev/stdin
d
}' input.txt
# outputs
abc
Tue Mar 17 10:53:53 CET 2020
line
Upvotes: 8
Reputation: 20032
You can use awk
for inserting output of some command in the middle of input.txt
.
The lines to be inserted can be the output of a cat otherfile
, ls -l
or 4 lines with a number generated by printf
.
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
Upvotes: 1
Reputation: 2500
I needed to template a few files with minimal tooling and for me the issue with above sed -e '/../r file.txt
is that it only appends the file after it prints out the rest of the match, it doesn't replace it.
This doesn't do it (all matches are replaced and pattern matching continues from same point)
#!/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}
Upvotes: -1
Reputation: 1063
sed '/^cdef$/r'<(
echo "line1"
echo "line2"
echo "line3"
echo "line4"
) -i -- input.txt
Upvotes: 33
Reputation: 929
This answer is easy to understand
Replace original file
FILENAME='app/Providers/AuthServiceProvider.php'
sed '/THEPATTERNYOUARELOOKINGFOR/Q' $FILENAME >>${FILENAME}_temp
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
grep -A 9999 'THEPATTERNYOUARELOOKINGFOR' $FILENAME >>${FILENAME}_temp
mv ${FILENAME}_temp $FILENAME
cat << EOL >> ${FILENAME}_temp
this variable will expand: $variable1
EOL
Upvotes: 0
Reputation: 14979
Another sed
,
sed '/cdef/r add.txt' input.txt
input.txt:
abcd
accd
cdef
line
web
add.txt:
line1
line2
line3
line4
Test:
sat:~# sed '/cdef/r add.txt' input.txt
abcd
accd
cdef
line1
line2
line3
line4
line
web
If you want to apply the changes in input.txt
file. Then, use -i
with sed
.
sed -i '/cdef/r add.txt' input.txt
If you want to use a regex as an expression you have to use the -E
tag with sed
.
sed -E '/RegexPattern/r add.txt' input.txt
Upvotes: 130
Reputation: 77185
Using awk
:
awk '/cdef/{print $0 RS "line1" RS "line2" RS "line3" RS "line4";next}1' input.txt
Explanation:
/.../
print $0
RS
is built-in awk
variable that is by default set to new-line
. 1
at the end results in printing of every other lines. Using next
before it allows us to prevent the current line since you have already printed it using print $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
To make changes to the file you can do:
awk '...' input.txt > tmp && mv tmp input.txt
Upvotes: 19
Reputation: 123668
Using GNU sed
:
sed "/cdef/aline1\nline2\nline3\nline4" input.txt
If you started with:
abcd
accd
cdef
line
web
this would produce:
abcd
accd
cdef
line1
line2
line3
line4
line
web
If you want to save the changes to the file in-place, say:
sed -i "/cdef/aline1\nline2\nline3\nline4" input.txt
Upvotes: 53