Modify a file without creating another file

You can use a vi script:

$ vi test.txt -c '%s/aaa/NNN/ | wq'
$ cat test.txt
NNN
NNN
bbb
ccc
ddd

You're simply automating what would normally be entered when using vi in command mode (accessed using Esc: usually):

% - carry out the following command on every line:

s/aaa/NNN/ - subtitute aaa with NNN

| - command delimiter

w - write changes to file

q - quit


Using sponge:

#!/bin/bash

pattern='aaa'
replacement='NNN'

while read -r line
do                                                                              
  printf '%s\n' "${line//$pattern/$replacement}"
done < "${1}"

Call with:

./script.sh test.txt | sponge test.txt

With ed, the line editor:

ed -s test.txt <<< $',s/pattern/replace/g\nw\nq'

or

ed -s test.txt <<IN
,s/pattern/replace/g
w
q
IN

or

printf '%s\n' ,s/pattern/replace/g w q | ed -s test.txt