sed (Stream Editor) is a robust command-line tool utilized in Linux and Unix-like operating systems for the purpose of parsing and modifying text.
It operates as a non-interactive text editor, which indicates that it automatically processes text according to a predefined set of editing commands or scripts, without the need for user interaction during the editing process.
sed reads input text line by line, applies specified operations, and outputs the modified text.
Its primary use is to perform various text transformations, including:
sed was developed from 1973 to 1974 by Lee E. McMahon which linguistic insight fostered the characteristic text-processing—as distinct from text-formatting—capabilities of the Unix V7, a major release of the Unix operating system in 1979. sed was based on the interactive editor ed and the earlier qed.
sed can be used in two ways :
In-line commands inside single quotes :
sed [OPTIONS] 'COMMANDS' inputfile(s)
Commands included in a script file , the same way as in awk seen previously :
sed [OPTIONS] -f scriptfile inputfile(s)
Some of the most frequently used options :
| Option | Description |
|---|---|
| -e | Add the script to be executed; can be used multiple times for several commands |
| -f | Read the sed script from the specified file instead of command line |
| -i | Edit files in place (modify the original file directly); optionally create a backup |
| -n | Suppress automatic printing of pattern space; output only lines explicitly printed |
| -r / -E | Use extended regular expressions (ERE) instead of basic ones |
| -s | Treat multiple input files separately rather than as a single continuous stream |
| --posix | Disable GNU extensions for strict POSIX compliance |
| --version | Display the sed version information and exit |
| --help | Show help summary of sed options and usage |
sed has various commands that we will see later. The s command (substitute) is the most commonly used, it replaces matching regex with replacement portion, the syntax is :
s/pattern/replacement/flags
Example : we'll use 3 files for the various examples throughout this page, a log file called books.log and the same files as in awk examples (students.txt and bank.csv ) :
| students.txt | bank.csv | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
and the books.log :
| books.log |
|---|
| 1. Les Misérables | Victor Hugo | Format: Poche | Pages: 1232 |
| 2. Madame Bovary | Gustave Flaubert | Format: Poche | Pages: 464 |
| 3. Le Père Goriot | Honoré de Balzac | Format: Poche | Pages: 368 |
| 4. Oscar et la dame rose | Éric-Emmanuel Schmitt | Format: Poche | Pages: 112 |
| 5. Monsieur Ibrahim et les fleurs du Coran | Éric-Emmanuel Schmitt | Format: Poche | Pages: 96 |
| 6. L'Étranger | Albert Camus | Format: Poche | Pages: 186 |
| 7. Stupeur et tremblements | Amélie Nothomb | Format: Poche | Pages: 160 |
| 8. Vernon Subutex 1 | Virginie Despentes | Format: Poche | Pages: 352 |
| 9. Couleur du temps | Leïla Slimani | Format: Poche | Pages: 224 |
| 10. La vie est facile, ne t'inquiète pas | Agnès Martin-Lugand | Format: Poche | Pages: 288 |
| 11. book book title | author author | size: pocket standard | Pages: 1000 500 500 500 |
Replace "success" with "achieved". By default, the sed command replaces the first occurrence of the pattern in each line and it won't replace the second, third...occurrence in the line :
sed 's/success/achieved/' students.txt
To replace only the nth occurrence of a word in a line (here replace the second occurrence of "book" with "Preston" ):
sed 's/book/Preston/2' books.log
The substitute flag /g (global replacement) specifies the sed command to replace all the occurrences of the string in the line.
sed 's/books/Preston/g' books.log
We can combine n and g to replace all the patterns from the nth occurrence of a pattern in a line :
sed 's/books/Preston/2g' books.log
Replace "500" with "1000" on the 11th line only
sed '11 s/500/1000/' books.log
Replace "success" with "achieved" from line 2 to line 8 :
sed '2,8 s/success/achieved/' students.txt
Replacing String from line 2 to the last line of students.txt :
sed '2,$ s/success/achieved/' students.txt
sed '11 s/^book/livre/' books.log
sed 's/success$/pass/g' students.txt
The & command is a special character which we'll see later in further detail.
sed 's/[0-9]/&,/' students.txt
By default, sed outputs the results of its alterations in the terminal (stdout), without modifying the original file. To directly apply the changes to the file, employ the -i (in-place) option. The syntax is : -i[SUFFIX], --in-place[=SUFFIX]
If suffix is provided, it takes a backup of the original file, otherwise the original file overwritten.
sed -i 's/success$/pass/g' students.txt
Create a backup before making changes, the file sudents.txt.bak is created automatically :
sed -i.bak 's/success$/pass/g' students.txt
4.1.1 delete line number n :
sed '11d' books.log
4.1.2 delete several chosen lines :
Delete all 19th century books
sed '1d;2d;3d' books.log
4.1.3 delete the last line :
sed '$d' books.log
4.1.4 delete lines from number n to m
Delete all contemporary books
sed '4,10d' books.log
4.1.5 delete from line number n to last line :
In our case almost the same previous command
sed '4,$d' books.txt
4.1.6 delete pattern matching line :
The syntax is : sed '/pattern/d' books.log
delete, for example, Éric-Emmanuel Schmitt's books
sed '/Éric-Emmanuel Schmitt/d' books.log
4.1.7 Delete the line whose pattern does not match :
delete all lines except those containing Éric-Emmanuel Schmitt
sed '/Éric-Emmanuel Schmitt/!d' books.log
4.1.8 delete empty lines :
Delete all blank (empty) lines from the file
sed '/^$/d' students.txt
| Symbol | Meaning |
|---|---|
^ |
beginning of the line |
$ |
end of the line |
nothing between ^ and $ |
means no characters on that line |
4.1.9 delete between two patterns
Delete all lines between two patterns, inclusive :
sed '/153/,/70/d' students.txt
The write command saves the pattern buffer contents into a file. SED creates a file with the given name and overwrites any existing file with the same name, so we have to be careful with name and extension.
sed -n 'w books.bak' books.log
The file books.bak is saved with exactly the same content as books.log. This command is the same as the cp command but saving the pattern buffer allows us to do much more, for example save a file with contemporary books removed :
sed -n -e '4,$d' -e 'w 19thONLY.log' books.log
Another example is pattern matching, so let's save in a separate file failing students :
sed -n '/fail/ w failing.txt' students.txt
or by author Éric-Emmanuel Schmitt's books :
sed -n '/Éric-Emmanuel Schmitt/ w Éric-Emmanuel-Schmitt.log' books.log
sed can read the content of a given file and display it when a pattern is matched. For instance, let's insert the contents of 19.log after the first to the 3rd lines.
echo "19th-century literature" > 19.log
sed '1, 3 r 19.log' books.log
another example with matching pattern :
echo "failure: below the pass mark" > fail.txt
sed '/fail/ r fail.txt' students.txt
The execute command, which is less common, runs a shell command from inside sed.
It's syntax : sed 's/REGEX/COMMAND/e' file
When there is pattern matching, the command is executed first and then the contents of the pattern buffer is displayed.
The whoami command :
sed '/Éric-Emmanuel Schmitt/ e whoami' books.log
Another example where the date is inserted before the first line :
sed '1 e date' books.log
The below command appends text after the specified 6th line in bank.csv :
sed '6 a payment,25-10-13,300,USD,3600' bank.csv
We can also use a matching pattern , so the text will be appended after the first occurrence of "USD" :
sed '/USD/ a payment,25-10-13,300,USD,3600' bank.csv
In this example "USD" appears once, but if there are multiple occurrences the text is appended after each match.
In contrast to append, the insert command operates similarly but places a line before a particular position.
The below command inserts the latest operation before the 2nd line in bank.csv :
sed '2 i payment,25-10-13,300,USD,3600' bank.csv
With a matching pattern :
sed '/USD/ i currency : USD ' bank.csv
The change command allows to replace an entire line with a new one. It also works with a line range.
sed '3 c purchase,15-08-07,100,USD,2500' bank.csv
The same way as for the previous commands we use here a matching pattern :
sed '/Victor Hugo / c 1. Bug-Jargal | Victor Hugo | Format: Poche | Pages: 272 ' books.log
Below, we will replace several lines ( from 4 to 11) with a single line :
sed '4, 11 c 1. Bug-Jargal | Victor Hugo | Format: Poche | Pages: 272 ' books.log
Two central buffers are used by Sed for text manipulation; they are identified as the pattern buffer (pattern space) and the hold buffer (hold space).
Pattern buffer :
Sed reads an input file or inline data line by line. The line that has been currently read is inserted into the pattern buffer which is the primary workspace where sed operates on the current line of input. Most used Sed commands, such as substitution (s), deletion (d), and printing (p), directly operate on the content of the pattern buffer. By default, the content of the pattern buffer is printed to standard output at the end of each processing cycle (unless the -n option is used), and then the pattern buffer is cleared to receive the next input line.
Hold buffer :
The hold space is a secondary buffer used for temporary storage of data that needs to be preserved across multiple lines or for more complex manipulations. Unlike the pattern buffer, the hold space, as the name denotes, maintains its content throughout cycles unless we intentionally modify it, and moreover it does not automatically print its contents.
Data cannot be directly manipulated within the hold space; instead, its contents must be transferred to the pattern buffer for processing. To interact with the hold space we can use the following commands :
| Command | Description |
|---|---|
| h | Copy the contents of the pattern space into the hold buffer (overwrite previous content). |
| H | Append the contents of the pattern space to the hold buffer (with a newline in between). |
| g | Replace the pattern space with the contents of the hold buffer. |
| G | Append the contents of the hold buffer to the pattern space (preceded by a newline). |
| x | Exchange the contents of the pattern space and the hold buffer. |
To put it plainly and resume, the pattern buffer can be seen as a scratchpad where we actively work ( on the current line), and the hold buffer can be seen as a separate storage area where we can temporarily save information for later use just like a clipboard.
Next, we'll briefly review some elementary examples involving prior commands.
The following command adds a space between lines :
sed 'G' books.log
In the above example :
To insert two blank lines :
sed 'G;G' books.log
To use matching patterns :
The above command
sed '/Éric-Emmanuel Schmitt/{x;p;x;}' books.log
The above command inserts a blank line before each line that contains Éric-Emmanuel Schmitt's book.
The three commands {x;p;x;} are executed when the pattern matches :
x
p
x
Then sed continues, eventually the line containing "Éric-Emmanuel Schmitt" is printed (either by sed's default behaviour or by the next instruction in the script), so we will have:
....
<blank line inserted>
4. Oscar et la dame rose | Éric-Emmanuel Schmitt | Format: Poche | Pages: 112
...
Thus, a blank line is inserted before the line containing "Éric-Emmanuel Schmitt".
This behavior is repeated for all lines where /Éric-Emmanuel Schmitt/ matches.
Simplified visual diagram
Suppose that the hold buffer begins empty, and consider the passage on line 4:
Note :
If "G" is used directly on the matching /Éric-Emmanuel Schmitt/ lines, this inserts a blank line after these lines.
The following example will work the same as the tac command which prints the input file in reverse order with the last line first.
sed -n '1!G;h;$p' books.log
The command '1!G;h;$p' contains three parts :
Detailed steps :
| Ligne | read content (initial pattern ) | Actions (1!G;h;$p) |
Pattern after execution | Hold after execution |
|---|---|---|---|---|
| 1 | 1. Les Misérables ... 1232 |
1st ligne → 1!G ignored → h |
1. Les Misérables ... 1232 |
1. Les Misérables ... 1232 |
| 2 | 2. Madame Bovary ... 464 |
G → add hold (1. Les Misérables ...) → h |
2. Madame Bovary ... 464\n1. Les Misérables ... 1232 |
same |
| 3 | 3. Le Père Goriot ... 368 |
G → add previous content (2+1) → h |
3. Le Père Goriot ... 368\n2. Madame Bovary ... 464\n1. Les Misérables ... 1232 |
same |
| 4 | 4. Oscar et la dame rose ... 112 |
G → adds (3+2+1) → h |
4. Oscar ... 112\n3. Le Père ... 368\n2. Madame ... 464\n1. Les Misérables ... |
same |
| 5 | 5. Monsieur Ibrahim ... 96 |
same operation | 5. Monsieur Ibrahim ...\n4. Oscar ...\n3. Le Père ...\n2. Madame ...\n1. Les Misérables ... |
same |
| 6 | 6. L'Étranger ... 186 |
adds all the previous | 6. L'Étranger ...\n5. Monsieur Ibrahim ...\n4. Oscar ...\n3. Le Père ...\n2. Madame ...\n1. Les Misérables ... |
same |
| 7 | 7. Stupeur et tremblements ... 160 |
same | 7. Stupeur et tremblements ...\n6. L'Étranger ...\n5. Monsieur ...\n4. Oscar ...\n3. Le Père ...\n2. Madame ...\n1. Les Misérables ... |
same |
| 8 | 8. Vernon Subutex 1 ... 352 |
same | 8. Vernon Subutex 1 ...\n7. Stupeur ...\n6. L'Étranger ...\n5. Monsieur ...\n4. Oscar ...\n3. Le Père ...\n2. Madame ...\n1. Les Misérables ... |
same |
| 9 | 9. Couleur du temps ... 224 |
same | 9. Couleur du temps ...\n8. Vernon ...\n7. Stupeur ...\n6. L'Étranger ...\n5. Monsieur ...\n4. Oscar ...\n3. Le Père ...\n2. Madame ...\n1. Les Misérables ... |
same |
| 10 | 10. La vie est facile ... 288 |
same | 10. La vie est facile ...\n9. Couleur ...\n8. Vernon ...\n7. Stupeur ...\n6. L'Étranger ...\n5. Monsieur ...\n4. Oscar ...\n3. Le Père ...\n2. Madame ...\n1. Les Misérables ... |
same |
| 11 | 11. book book title ... 1000 500 500 500 |
G → add everything else then $p → prints |
11. book book title ...\n10. La vie est facile ...\n9. Couleur ...\n8. Vernon ...\n7. Stupeur ...\n6. L'Étranger ...\n5. Monsieur ...\n4. Oscar ...\n3. Le Père ...\n2. Madame ...\n1. Les Misérables ... |
same |
The following example will append lines containing "Amélie" or "Agnès" to the hold space and then print the accumulated content.
sed -n '/Amélie/H; /Agnès/H; ${g;p}' books.log
We'll print the line immediately before a pattern match, in this case "Camus" :
sed -n '/Camus/{g;1!p};h' books.log
The above command contains 2 mains parts :
After the block, for each line (whether it matches or not), the h command is executed. h copies the current line (the pattern buffer for that line) to the hold buffer. Thus, at the end of processing a line, the hold buffer contains the current line, making it the “previous” line for the next iteration.
In summary:
Each line is stored in the hold buffer via h.
When a line containing “Camus” is encountered, the current line (pattern space) is replaced with the contents of the hold buffer (previous line) via g, then this content is printed (if it is not the first line) via 1!p.
The line containing “Camus” itself is not printed by this block (it could be printed by default if -n is not used).
The overall effect is to locate “Camus” and move up one line to print it.
Displaying the contents of a file is one of the fundamental tasks we carry out. The print command prints the contents of the pattern buffer, given that all input lines are printed by default.
The p command is often paired with the -n option, which stops default printing, allowing us to display only the filtered lines.
6.1.1 default printing behavior
In case the -n option is not used the print command will cause redondant line, each line displayed twice : one from the default behavior of sed which prints the pattern buffer and the other due to p.
sed 'p' books.log
To display the file normally, similar to cat command, the right syntax should be :
sed -n 'p' books.log
or
sed '' books.log
6.1.2 Print a specific line
Print the second line only :
sed -n '2p' books.log
6.1.3 Print a range of lines
Print the 19th century books only, from the first to third line :
sed -n '1, 3 p' books.log
Print from the fourth line to last line :
sed -n '4, $ p' books.log
6.1.4 Print a range of lines using operator +
Print 6 lines more starting from line 4 (included) :
sed -n '4, +6 p' books.log
6.1.5 Print a range of lines using operator ~
Beginning at line 1, sed processes every 2 lines; in this case, we print only the odd-numbered lines:
sed -n '1~2 p' books.log
To print the even lines only :
sed -n '2~2 p' books.log
6.1.6 Print using matching pattern
same as: grep 'Camus' books.log :
sed -n '/Camus/p' books.log
find the first occurrence of the pattern "120" and print the remaining lines :
sed -n '/140/,$ p' students.txt
print all the lines between the patterns 4 and 10 :
sed -n '/^4./, /^10./ p' books.log
4. Oscar et la dame rose | Éric-Emmanuel Schmitt | Format: Poche | Pages: 112
5. Monsieur Ibrahim et les fleurs du Coran | Éric-Emmanuel Schmitt | Format: Poche | Pages: 96
6. L'Étranger | Albert Camus | Format: Poche | Pages: 186
7. Stupeur et tremblements | Amélie Nothomb | Format: Poche | Pages: 160
8. Vernon Subutex 1 | Virginie Despentes | Format: Poche | Pages: 352
9. Couleur du temps | Leïla Slimani | Format: Poche | Pages: 224
10. La vie est facile, ne t'inquiète pas | Agnès Martin-Lugand | Format: Poche | Pages: 288
Matching pattern and + operator :
sed -n '/^2./, +8 p' books.log
p can be a flag for the substitute command which in this case only prints the processed line if the substitution command succeed.
sed -n ' s/book/livre/p' books.log
Perform multiple substitutions :
sed -n -e '2,8 s/success/achieved/p' -e '1,8 s/grade/mark/p' students.txt
ID name forename mark result
120 weslati firas 85 achieved
140 dridi mohamed 80 achieved
145 yacoubi salah 95 achieved
147 benrejeb wissal 90 achieved
148 mekki ryan 75 achieved
152 mbanebe philippe 80 achieved
filter + substitute
sed -n '/^14[0-9]/ s/success/PASS/gp' students.txt
140 dridi mohamed 80 PASS
145 yacoubi salah 95 PASS
147 benrejeb wissal 90 PASS
148 mekki ryan 75 PASS
The other way to delete command :
-n option paired with !p flag is equivalent to delete command :
sed -n '/^14[0-9]/!p' students.txt
ID name forename grade result
120 weslati firas 85 success
152 mbanebe philippe 80 success
153 sako aminata 70 fail