File inclusion processing by GNU sed one-liner

This page describes how to insert a text file into another text file with one-liner program of GNU sed. This page also publishes the Python script to create the featured image.

(There is the Japanese(日本語) page.)

(Last updated date: February 21, 2021)

Preface

I searched on the web how to insert a text file into another text file, like the #include directive in the C programming language. In the process of its work, I also read the GNU sed manual. Then, I found that it can be easily achieved with One-liner program of GNU sed, so I explain it below.

Moreover, the featured image placed at the top of this page is created with the Python script. The script is published in the last half of this page.

File inclusion processing by GNU sed

The OS and sed used for the operation check are Ubuntu 18.04 and GNU sed 4.4.

Here are three examples.

Example 1

First, the simple example is shown below.

$ cat main.txt
main 1
main 2
include 'sub.txt'
main 3
$ cat sub.txt 
sub 1
sub 2
$ sed -e 's/^include/cat/e' main.txt
main 1
main 2
sub 1
sub 2
main 3

The sed function used here is the e flag (execute) of the s command (substitute (replace)). This function executes the replaced string as the shell command. This is the GNU sed extension. POSIX sed does not have this function.

In this example, after replacing the “include” string at the beginning of the line with “cat”, the result of executing the shell command “cat file-name” is imported into the text file.

Example 2

Next, here’s the example of inserting two Python script files into the Markdown file.

$ cat hello.py 
print('Hello, world!')
$ cat number.py 
for i in range(5):
    print(i)
$ cat python.md 
This is a Python script.

```python
include 'hello.py'
```

This is another Python script.

```python
include 'number.py'
```

$ sed -e 's/^include/cat/e' python.md 
This is a Python script.

```python
print('Hello, world!')
```

This is another Python script.

```python
for i in range(5):
    print(i)
```

Example 3

In the two examples above, the entire content of the specified file in the text file is imported.

In the last example, by changing the form a little, only a part of the specified file is imported.

$ cat letter.txt 
aaa
bbb
$ cat number.txt 
111
222
333
444
555
666
$ cat inclusion.txt 
sed cat 'letter.txt'
----
sed head -2 'number.txt'
----
sed sed -n '3,4p' 'number.txt'
----
sed tail -n 2 'number.txt'
$ sed -e 's/^sed//e' inclusion.txt 
aaa
bbb
----
111
222
----
333
444
----
555
666

In this example, after removing the “sed” string at the beginning of the line, the rest of the string is executed as the shell command, and the result is captured. With this method, the shell command can be written freely, so flexible file inclusion can be specified.

The “include” and “sed” strings at the beginning of the lines shown in the examples so far are just markers for searching. These can be replaced with any string. For example, you can replace “include” with “#include”, or replace “sed” with “#execute” or “#run”.

Python script to create the featured image

The featured image placed at the top of this page is created based on the Python script shown below.

#!/usr/bin/env python3

# Python script to make the featured-image (SVG format).

# This script is tested with Python 3.6.9 and svgwrite 1.4 on Ubuntu 18.04.

# Public Sans 1.008 is licensed under the SIL Open Font License 1.1
# https://public-sans.digital.gov/

import random
import colorsys
import svgwrite

random.seed(0)

# Attribute values of image
image_size = (image_width, image_height) = (960, 600) # 16:10

# Drawing object of svgwrite
dwg = svgwrite.Drawing(filename='feature-using-font.svg', \
    size=image_size, profile='full')

# Background rectangle of image
dwg.add(dwg.rect(insert=(0, 0), size=image_size, \
    fill=svgwrite.rgb(246, 246, 246)))

# Lines
for i in range(106):
    line_x      = random.randint(0, image_width)
    line_y      = random.randint((- round(image_height / 3)), image_height)
    line_length = random.randint(   round(image_height /15) , image_height)

    line_width  = round(random.uniform(0.1, 10), 4)

    saturation  = random.uniform(0.1, 0.9)
    line_rgb    = [j*100 for j in colorsys.hls_to_rgb(0.5, 0.5, saturation)]

    dwg.add(dwg.line(start=(line_x, line_y), \
        end=(line_x, (line_y + line_length)), stroke_width=line_width, \
        stroke=svgwrite.rgb(*line_rgb, mode='%')))

# Background rectangle of text
dwg.add(dwg.rect(insert=(220, 180), size=(520, 240), fill='white'))

# Frame rectangle of text
dwg.add(dwg.rect(insert=(224, 184), size=(512, 232), fill='none', \
    stroke='black', stroke_width=2))

# Text 'File inclusion'
dwg.add(dwg.text('File inclusion', fill='black', \
    text_anchor='middle', insert=((image_width /2), 290), \
    font_family='Public Sans', font_weight='bold', font_size=76))

# Text 'by GNU sed'
dwg.add(dwg.text('by GNU sed', fill='black', \
    text_anchor='end', insert=(717, 380), \
    font_family='Public Sans', font_weight='bold', font_size=48))

# Save to the SVG file
dwg.save()

This script uses the following external Python package:

The geometric pattern in the featured image consists only of lines (SVG lines). These lines are randomly generated by the script. The use of vertical lines is decided in advance. However, the other line attributes, in other words, the line position, length, width, and color, are all decided based on random numbers in Python.

When you run this Python script, it will create the SVG file shown below.

This SVG file uses the Public Sans font. If you view this SVG file in an environment where this font is not installed, the font will not be displayed as intended in the Python script above.

Accordingly, the SVG file whose font is outlined using Inkscape is shown below. With this file, the font part will be displayed as intended even in an environment where the Public Sans font is not installed.

Similarly, the file converted to PNG format using Inkscape is the image placed at the top of this page.

Comments

Popular posts from this blog