This is the fifth episode of our GNU sed command examples series. This episode contains another 10 command examples covering things such as deleting source code's comments, converting image files (along with ImageMagick tool), and inserting a single or multiple lines to a file. For you just started, we recommend you to read the first until the fourth episode before this one.
Text Examples
text12.txt:
// this is C-style
comment line
// this is the
second line of comment
#include <stdio.h>
int main()
{
printf("This
is the code line\"); // this is a comment right beside a code
line
return 0; // this
is the second comment right beside a return value code
}
text13.txt:
#!/bin/bash
# this is a single
line comment
echo "Hello!"
# this is the last
comment line
text14.txt:
/* this is the
slash-asterisk style of comment
it is multiple
lines of comment
it ends with an
asterisk-slash sequence
*/
#include <stdio.h>
int main()
{
/* this is another
slash-asterisk style of comment
it should be
deleted by GNU sed
*/
printf("Hello\n");
return 0;
}
41. Delete Comment Lines (Double Slash Style)
Command Examples:
sed '/^\/\/.*$/d'
text12.txt
Output Examples:
master@master:/tmp$
sed '/^\/\/.*$/d' text12.txt
#include <stdio.h>
int main()
{
printf("This
is the code line\"); // this is a comment right beside a code
line
return 0; // this
is the second comment right beside a return value code
}
master@master:/tmp$
Explanation:
This command is
basically just a single ‘d’ (delete) command of sed (already
explained in Episode
1). What this command do is to delete all lines beginning with
double slash (`//`). This command has a basic syntax like this:
‘/ /d’
then we add the main
keyword, the double slash:
‘////d’
then we add
backslashes to make sed understand the slashes are literal slashes (this is called escaping):
‘/\/\//d’
then we add `^`
(caret) in the beginning so sed will match the double slash only for
the beginning of line:
‘/^\/\//d’
then we add `.*`
(dot asterisk) so sed will match the following words or a sentence
after the double slash:
‘/^\/\/.*/d’
finally we add `$`
(dollar) so sed understands this whole regex to match a single line
from the beginning to the end:
‘/^\/\/.*$/d’
42. Delete Comment Lines (Double Slash Style, Except At Line Beginning)
Command Example:
sed
's+\([^!]\/\/.*$\)++g' text12.txt
Output Example:
master@master:/tmp$
cat text12.txt
// this is C-style
comment line
// this is the
second line of comment
#include <stdio.h>
int main()
{
printf("This
is the code line\"); // this is a comment right beside a code
line
return 0; // this
is the second comment right beside a return value code
}
master@master:/tmp$
sed 's+\([^!]\/\/.*$\)++g' text12.txt
// this is C-style
comment line
// this is the
second line of comment
#include <stdio.h>
int main()
{
printf("This
is the code line\");
return 0;
}
master@master:/tmp$
Explanation:
This example is basically the same with the example number 41. The
only difference is a sequence of regex `[^!]`. This regex tells sed
to match (in this example, to delete) every regex in the beginning of
line. But because there is a single exclamation mark (`!`)
following, the mark of reversal, sed reverses the result to be
to delete every regex matches except
in the beginning of line. So in this example, sed deletes every
side comment, the comment staying beside the code line. See the
printf and return lines.
43. Delete Comment Lines (Hash Style)
Command Example:
sed '/^#[^!].*.$/d'
text13.txt
Output Example:
master@master:/tmp$
sed '/^#[^!].*.$/d' text13.txt
#!/bin/bash
echo "Hello!"
master@master:/tmp$
Explanation:
This example is
special for shell scripting commenting style. This is basically just
the same with example number 41 and 42, except it is much simpler.
There is no backslash so you won’t get confused. The only
difference is a `#` (hash) as a replacement of double slash (`//`).
But be careful, there must be a mark to exclude the line that has `!`
right after the `#`. That mark is the sequence (`[^!]`) from the
example number 42. So this example number 43 deletes all hash-leaded
lines except the line leaded by a single shebang (the `#!`
sequence).
43. Delete Comment Lines (Slash-Asterisk Style)
Command Example:
sed '/\/\*/,/\*\//d'
text14.txt
Output Example:
master@master:/tmp$
sed '/\/\*/,/\*\//d' text14.txt
#include <stdio.h>
int main()
{
printf("Hello\n");
return 0;
}
master@master:/tmp$
Explanation:
This example takes advantage of ‘d’ command double address. The
first address is a regex, and the last address is also a regex. This
means sed will delete all lines between the first and the last
regexes match. The basic syntax is like this:
‘/ /,/ /d’
then we put the first regex with the slash-asterisk and the last
regex with the asterisk-slash:
‘/ /*/,/*/ /d’
finally we escape every slash and asterisk with backslash:
'/\/\*/,/\*\//d'
44. Boolean Operator OR
Command Example:
sed -E -n
'/this|line|return/p' text14.txt
Output Example:
master@master:/tmp$
sed -E -n '/this|line|return/p' text14.txt
/* this is the
slash-asterisk style of comment
it is multiple
lines of comment
/* this is another
slash-asterisk style of comment
return 0;
master@master:/tmp$
Explanation:
This example is a new thing here because it contains `-E` option.
This option makes sed uses the Extended Regular Expression (ERP) so
it can use pipe (`|`) without escaping (or, without backslash). A
single pipe character means logical OR in a regex sequence. So, this
command means print any line containing either “this” or “line”
or “return” keyword. As the result, it prints only the lines
containing either of them.
45. Boolean Operator AND
Command Examples:
-
sed -n '/this.*comment/p' text14.txt
-
sed -n '/this.*slash.*comment.*/p' text14.txt
Output Examples:
(1)
master@master:/tmp$
sed -n '/this.*comment/p' text14.txt
/* this is the
slash-asterisk style of comment
/* this is another
slash-asterisk style of comment
(2)
master@master:/tmp$
sed -n '/this.*slash.*comment.*/p' text14.txt
/* this is the
slash-asterisk style of comment
/* this is another
slash-asterisk style of comment
master@master:/tmp$
Explanation:
This example is
basically not containing boolean AND at all. But it mimics boolean
AND with the `.*` (dot asterisk) regex. This means, the matched
result should be the line containing both the before and the after
keyword. Hence, you see the result is always [keyword1]...[keyword2]
in one line. The second example shows that you may put any of this
AND sequence (`.*`) to match keywords as many as you want in a single
line.
46. Multiple Convert Images (PNG to JPEG)
Command Example:
for i in *.png; do
convert -verbose "$i" "`echo $i | sed
's/.png/.jpeg/g'`"; done
Output Example:
master@master:~/Pictures/linux-mint-18-cinnamon$
for i in *.png; do convert -verbose "$i" "`echo $i |
sed 's/.png/.jpeg/g'`"; done
Screenshot from
2016-07-16 03-13-28.png PNG 658x413 658x413+0+0 8-bit sRGB 85.3KB
0.020u 0:00.030
Screenshot from
2016-07-16 03-13-28.png=>Screenshot from 2016-07-16 03-13-28.jpeg
PNG 658x413 658x413+0+0 8-bit sRGB 66.6KB 0.020u 0:00.010
Screenshot from
2016-07-16 03-14-01.png PNG 1366x768 1366x768+0+0 8-bit sRGB 412KB
0.060u 0:00.070
Explanation:
Please don’t see
them if the output lines confuse you. Just see the command. That
command is basically just one of ImageMagick commands, the `convert`
command. The basic syntax of convert command is very simple:
convert [source]
[destination]
then the single
command sample (PNG to JPEG) is:
convert a.png a.jpeg
now you see that the
single direct converting command is very simple if you know
the [source] file name. But now, we should make `convert` command to
do converting without knowing the [sources] file names.
The `convert` must
do converting for all files in a directory automatically. This
happens with bash looping. And the greatness of bash looping is where
we can put a variable to give `convert` every file name available. So
it will convert the whole files automatically, just like a revolver
gun. So the further command syntax is:
convert
“[source_variable]” “[destination_variable]”
the
[source_variable] is replaced by the `$i` variable as shown in the
example. And the most wonderful is the [destination_variable] is
replaceable with command lines, including echo and
sed, by using escaping apostrophes around. So, we expect sed
to replace every “.png” string into “.jpeg” string, and the
sed output will be the [destination_variable] automatically. Sed can
do it because echo send it the file name (the `$i` content) through
the pipeline (`|`). So in the end, the whole `convert` command
complete, and bash looping will loop that command to every PNG file
in a directory.
convert "$i"
"`echo $i | sed 's/.png/.jpeg/g'`"
47. Multiple Convert Images (JPEG to PNG)
Command Example:
for i in *.jpeg; do
convert -verbose "$i" "`echo $i | sed
's/.jpeg/.png/g'`"; done
Output Example:
master@master:~/Pictures/linux-mint-18-cinnamon/jpeg/jpeg$ for i in
*.jpeg; do convert -verbose "$i" "`echo $i | sed
's/.jpeg/.png/g'`"; done
Screenshot from 2016-07-16 03-13-28.jpeg JPEG 658x413 658x413+0+0
8-bit sRGB 66.6KB 0.020u 0:00.019
Screenshot from 2016-07-16 03-13-28.jpeg=>Screenshot from
2016-07-16 03-13-28.png JPEG 658x413 658x413+0+0 8-bit sRGB 210KB
0.100u 0:00.109
Screenshot from 2016-07-16 03-14-01.jpeg JPEG 1366x768 1366x768+0+0
8-bit sRGB 110KB 0.020u 0:00.019
Explanation:
This is exactly the same with the example number 46 except the *.jpeg
addressing and we reverse position of .jpeg and .png in the
substitute command. See the two bolded parts of text below:
for i in *.jpeg; do convert -verbose "$i"
"`echo $i | sed 's/.jpeg/.png/g'`"; done
48. Insert A Single Line
Command Examples:
-
sed '1i # THIS IS A NEW LINE' text13.txt
-
sed '3i # THIS IS A NEW LINE' text13.txt
Output Examples:
(1)
master@master:/tmp$
sed '1i # THIS IS A NEW LINE' text13.txt
# THIS IS A NEW LINE
#!/bin/bash
# this is a single
line comment
echo "Hello!"
# this is the last
comment line
(2)
master@master:/tmp$
sed '3i # THIS IS A NEW LINE' text13.txt
#!/bin/bash
# this is a single
line comment
# THIS IS A NEW LINE
echo "Hello!"
# this is the last
comment line
master@master:/tmp$
Explanation:
This is a new sed
command for our example series. This is ‘i’ command, a GNU sed
extension (so it is available only in GNU sed, not in UNIX sed). This
command in this example has a basic syntax like this:
‘[number]i [text]’
[filename]
then we turn it into
this:
‘3i # THIS IS A
NEW LINE’
finally it will
insert the line after space after the ‘i’ command to the desired
file, to the line number we specified before (line number 3).
50. Insert Multiple Lines
Command Example:
sed '3i # THIS IS A
NEW LINE\n# THIS IS ANOTHER LINE' text13.txt
Output Example:
master@master:/tmp$
sed '3i # THIS IS A NEW LINE\n# THIS IS ANOTHER LINE' text13.txt
#!/bin/bash
# this is a single
line comment
# THIS IS A NEW LINE
# THIS IS ANOTHER
LINE
echo "Hello!"
# this is the last
comment line
master@master:/tmp$
Explanation:
This
example is exactly the same with the example number 49 but the `\n`
sequence. This `\n` is
widely used in many of POSIX related program, as well as any
programming language, as a “newline”. So it will separate the two
sentences with a newline, so the first will be in line number 3
and the later will be in line number 4.