sed -n: suppress automatic printing (and why lines print twice)
- tool
- sed
- command
- sed
- flag
- -n, --quiet, --silent
- default
- off (every line is printed at the end of each cycle)
sed -n turns off sed's automatic printing. Normally sed prints the pattern space after running the script on each line, so every input line appears in the output whether or not the script touched it. With -n nothing is printed unless a command asks for it: the p command, the p flag of s///, or =, l and w. That is why sed -n '/pattern/p' behaves like grep, while sed '/pattern/p' prints the matching lines twice.
Without and with -n
printf 'host=a\nport=80\n' > app.conf
sed '/host/p' app.conf
echo '--- with -n'
sed -n '/host/p' app.conf
echo '--- s///p without and with -n'
sed 's/port=80/port=8080/p' app.conf
echo '--'
sed -n 's/port=80/port=8080/p' app.confOutput
host=a host=a port=80 --- with -n host=a --- s///p without and with -n host=a port=8080 port=8080 -- port=8080
Without -n, the p command adds a second copy of each selected line. With -n, only the explicit prints remain, so sed -n 's/.../.../p' prints just the lines where the substitution happened.
Commands that print under -n
| Command | Output under -n |
|---|---|
| p | The current pattern space |
| s/x/y/p | The line, only if the substitution was made |
| = | The current line number |
| l | The line with non-printing characters made visible |
| w FILE | Writes the line to FILE (not to standard output) |
| P | The pattern space up to the first newline |
| (anything else) | Nothing: d, s without p, a and i still work |
a and i text is still output under -n, because it is queued separately from the pattern space.
Common -n idioms
seq 1 20 > n.txt
sed -n '5,7p' n.txt | tr '\n' ' '; echo
sed -n '$=' n.txt
sed -n '/^1[0-2]$/p' n.txt | tr '\n' ' '; echo
printf '#n\n/^3$/p\n' > quiet.sed
sed -f quiet.sed n.txtOutput
5 6 7 20 10 11 12 3
sed -n '$=' counts lines like wc -l. The script file starting with #n acts like -n. Line ranges are covered in detail in sed -n: print specific lines.
The -n -i trap
printf 'host=a\nport=80\n' > app.conf
sed -n -i 's/port=80/port=8080/p' app.conf
cat app.confOutput
port=8080
The file lost the host=a line: with -i, the output replaces the file, and under -n only the substituted line was printed. Use plain sed -i 's/.../.../' for in-place replacement, as in sed -i find and replace.
Platform notes
-n is POSIX and behaves the same in GNU sed, BSD sed and BusyBox. The long forms --quiet and --silent are GNU only.
FAQ
Why does sed print every matching line twice?
Because p prints the line and sed prints it again at the end of the cycle. Add -n to turn off the automatic print, so only the lines you print with p appear: sed -n '/pattern/p'.
Can I combine sed -n with -i?
Yes, but the file then keeps only the lines the script prints explicitly. sed -n -i 's/a/b/p' file deletes every line that had no substitution. Drop -n when editing in place unless that is what you want.
What does #n at the top of a sed script mean?
If the first two characters of a script file are #n followed by a newline, sed behaves as if -n had been given. It is the POSIX way to make a script quiet without changing the command line.