Combine and Transform Text Files

LinuxBeginner
Practice Now

Introduction

Text files can relate in different ways. Sometimes characters need normalization; sometimes two files correspond by line position; sometimes records share a key. Choosing the matching tool is more important than memorizing options.

This lab introduces three focused tools: tr transforms a character stream, paste combines lines by position, and join combines sorted records by a shared field. You will observe each input and verify the resulting file before building a small report.

Translate and Clean a Character Stream

In this step, you will use tr to translate characters, squeeze repeated separators, and delete unwanted characters.

Create a deliberately inconsistent line. cat -A then makes normally invisible details visible: spaces remain visible as gaps, and $ marks the line ending. This helps you see exactly what needs cleaning:

cd /home/labex/project/text-combine-lab
printf '  API,,,Worker,,WEB  \n' > raw-services.txt
cat -A raw-services.txt

tr SET1 SET2 replaces characters from the first set with corresponding characters from the second. The portable classes [:upper:] and [:lower:] represent uppercase and lowercase letters:

tr '[:upper:]' '[:lower:]' < raw-services.txt

Now pipe three stages together. The first translates letter case; tr -s ',' squeezes each run of repeated commas into one comma; tr -d ' ' deletes space characters; and tee displays and saves the final stream:

tr '[:upper:]' '[:lower:]' < raw-services.txt | tr -s ',' | tr -d ' ' | tee clean-services.txt

The result should be api,worker,web. tr reads a stream; it does not edit the input file in place.

Merge Corresponding Lines with Paste

In this step, you will combine files whose first lines correspond, whose second lines correspond, and so on.

Create one column of service names and one column of owners:

cd /home/labex/project/text-combine-lab
printf '%s\n' api worker web > services.txt
printf '%s\n' team-blue team-green team-blue > owners.txt

paste places corresponding lines side by side, using a tab by default:

paste services.txt owners.txt

Choose comma as the delimiter with -d, and use tee to display and save a CSV-like file:

paste -d, services.txt owners.txt | tee service-owners.csv

paste does not compare keys. If one file has missing or reordered lines, the pairing changes.

Join Records by a Shared Key

In this step, you will combine records by a matching first field rather than by line position.

Create two space-delimited tables in different orders:

cd /home/labex/project/text-combine-lab
printf '%s\n' 'web 8080' 'api 9000' 'worker 9100' > ports-unsorted.txt
printf '%s\n' 'worker active' 'web active' 'api maintenance' > states-unsorted.txt

join expects both inputs sorted by the join field. Prepare sorted copies. In sort -k1,1, -k selects a key and 1,1 means “start and end with field 1,” so only the service name controls ordering:

sort -k1,1 ports-unsorted.txt > ports.txt
sort -k1,1 states-unsorted.txt > states.txt

Inspect them, then join matching field 1 values:

cat ports.txt
cat states.txt
join ports.txt states.txt | tee service-details.txt

Each result contains the shared service key once, followed by the port and state.

Build a Readable Service Report

In this step, you will reshape the joined records without changing the source tables.

Convert spaces to commas to produce a simple report:

cd /home/labex/project/text-combine-lab
tr ' ' ',' < service-details.txt | tee service-report.csv

Add a header by grouping two commands. Braces send both commands' output into one redirection:

{ echo 'service,port,state'; cat service-report.csv; } > service-report-with-header.csv
cat service-report-with-header.csv

Count data records without counting the header:

tail -n +2 service-report-with-header.csv | wc -l | tr -d ' ' > service-count.txt
cat service-count.txt

This workflow preserves small, inspectable stages: normalized data, joined data, formatted data, then a final report.

Summary

You used tr for character-level normalization, paste for positional columns, and join for sorted key relationships. You then combined small stages into a readable CSV report while keeping the original inputs intact.