Ade Malsasa Akbar contact
Senior author, Open Source enthusiast.
Tuesday, July 26, 2016 at 13:41



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:

  1. sed -n '/this.*comment/p' text14.txt
  2. 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:

  1. sed '1i # THIS IS A NEW LINE' text13.txt
  2. 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.