FUNDAMENTALS A Complete Guide for Beginners
Reading input interactively from the commands pipe is a common task in Bash scripting. In the case of collecting user data, processing commands, or building interactive scripts, understanding how to read from Bash piping is essential. Bash provides different ways to read input from another command using pipe. In this tutorial, I will discuss the basics of pipe, and how you can use it to read input.
What is Piping?
Piping refers to the process of sending the output (usually text) of one program or command as input to another program or command. This allows for the chaining of commands together, creating a pipeline where the output of one process becomes the input of the next process. In Unix-like operating systems, including Linux and macOS, piping is a fundamental feature of the command-line interface (CLI) and is used to perform a wide range of tasks efficiently by combining simple commands. Piping is represented using the vertical bar symbol “|”.
How Does Piping Work?
Actually, piping passes the output of a command (stdout) as the input of another command (stdin). Here’s an example to illustrate how piping works in practice:
cat myfile.txt | grep "keyword" | sort | uniq
Pipes are unidirectional. As a result, the input for the next command is redirected from the output of the previous command, and so on. This allows you to chain multiple commands together to perform more complex data processing tasks efficiently.
5 Cases of How to Read From Pipe in Bash
In Bash, you can read from a pipe using various methods depending on your specific use case. Also, through piping, you can operate many more command-line operations. In this tutorial, I’ll show you five common ways to read data from a pipe.
1. Using the “read” Command in a “while” Loop
You can use the read
command with a while loop
to read from a pipe within a bash script. The read commands read a line from the input and assign it to a variable.
Now, follow the below steps to learn how to use the read command to read form pipe in Bash:
#!/bin/bash
cat names.txt | while read name; do
echo "$name"
done
Here, the cat names.txt
redirects the contents of the names.txt file to a while loop through a pipe. This while loop
reads each line of input from the previous cat
command, and for each line, it assigns the line to the name variable. Finally, echo "$name"
uses the echo command to print the value of the name variable to the terminal.
You can preview the content of names.txt if you want by the command:
cat names.txt
Running the script with ./shownames.sh
will show the following output:
It takes the file names.txt as input and passes the content of the file line by line to while loop through the pipe and then echoes each line to the terminal.
2. Using the “read” Command in Terminal
You can use the read
command to read from a pipe within a script in the terminal. The read command reads a line from stdin and assigns it to a variable. For example,
echo “Hello LinuxSimply” | { read name; echo “msg=$name”; }
echo
command outputs the string Hello LinuxSimply, and the pipe operator ( | )
sends the output as input for the next command, where the read
command reads input from the pipe and assigns it to the variable name. Finally, the echo
command echoes the variable value.
From the above image, you can see the read command successfully reads from piped output & later the value is displayed.
Again, if you want to separate the input into multiple pieces and read each of them to variable through the pipe, you can use IFS(Internal Field Separator). Check the process using the following commands:
IFS="-"
echo "Hello-world!" | (read var1 var2; echo $var1; echo $var2)
IFS is a special variable in Bash that specifies the characters used to separate fields or words when splitting strings. In the above command, I set the value of the IFS variable to a hyphen (“-“). Then, echo redirects the string “Hello-LinuxSimply” to the read command through a pipe. Read command splits the input from the pipe into two parts based on the hyphen (as defined by the IFS). The first part is assigned to the variable var1, and the second part is assigned to var2. Finally, echo prints the two variables.
The output shows that the input Hello-LinuxSimply is separated by a hyphen (-) and stored Hello in var1 and LinuxSimply in var2.
3. Using Function
In Bash, you can pipe the output of a command to a function using process substitution. Process substitution allows you to treat the output of a command as if it were a file, which you can then pass as an argument to a function.
Now, to read from a pipe to a function, check the script:
#!/bin/bash
function read_stdin()
{
cat > file.txt
}
read_stdin
The script contains a function named read_stdin(). After that, inside the code block { cat > file.txt; }
, the cat command reads input from the standard input (stdin), and the output is redirected to a file named file.txt using the >
operator. Finally, after defining the function, read_stdin calls the defined function.
At this stage, let’s pass the output of the date command to this script:
date | ./func.sh
This should write the output of the date
command into a file called file.txt. Run the below command to preview it:
cat file.txt
However, the function doesn’t need an argument or variable declared to accept or hold standard input. It is automatically passed from the command line and inherited from the parent process into the function. Run the below script to read a string passed through a pipe using the function:
#!/bin/bash
# Define a function that processes input
my_function() {
while IFS= read -r line; do
#Your processing logic here
echo "Processed: $line"
done
}
# Pipe the output of a command to the function
echo "Hello, LinuxSimply" | my_function
The script contains a function named my_function(). After that, the while IFS= read -r line;
reads lines from a file or input stream line by line. Inside the block do … done I used echo "Processed: $line"
as an example command that processes input. You can replace the processing logic inside this function with your own. Finally, I piped the output of the echo command to my_function using ‘|’.
4. Using Lastpipe Feature
When you use piping with read to assign a value to a variable, the shell creates a new sub-shell where the piped command is executed. Therefore, the value is lost. So, the variable cannot be used. However, when we use the lastpipe option in the recent versions of bash, we can pipe the output of a command, such as echo, to read. The read statement will then assign the output to a variable.
Using the lastpipe feature, the last command is executed in the current shell instead of a new sub-shell. For that reason, the environment retains its value. By default, this option is disabled. Use the below command to enable it.
shopt -s lastpipe
set +m
- shopt: Shopt (shell option) is a Bash built-in command used to manipulate shell options.
- -s: The –s option is used with shopt to set (enable) a shell option.
- lastpipe: lastpipe is the name of the shell option that changes the behavior of the last command in a pipeline.
- set +m: Run a command in the background but not actively report its status.
Now, to test the lastpipe, let’s use a command with a pipe.
cal -A1 | read month
This command passes the output of cal command to month variable through a pipe and the variable reads the first line of the cal output.
echo “$month”
After configuring the shell for lastpipe, month variable read the output of cal -A1
command through pipe.
5. Using Command Substitution
Command substitution in Bash allows you to capture the output of a command or a pipeline and use it as an input or argument to another command. For example, you can create a Bash script that counts the number of lines in a text file provided to it through pipe.
Check the script below to know how to read from pipe with the command substitution approach:
#!/bin/bash
#Read input from a pipe
input_data=$(cat -)
#count the line number
line_count=$(echo "$input_data" | wc -l)
#Print the result
echo "The number of lines is : $line_count"
The $(cat -)
captures the input data from pipe and echo "$input_data" | wc -l
counts the number of lines by the wc command in the input_data variable. Finally, the echo command prints the number of lines in the input.
First, preview the content of names.txt.
cat names.txt
Now run the following command:
cat names.txt | ./count_lines.sh
This will pass the contents of names.txt through the pipe to count_lines.sh. Then the script will count and print the number of lines in it. The output will be as below: The output image shows the number of lines in the names.txt file.
Conclusion
Reading from piping in bash is a powerful technique in Unix-like systems, enabling the creation of complex pipelines using simple, modular commands. As piping allows you to chain multiple commands together to perform more complex data processing tasks efficiently, reading from piping can be a vital and fundamental concept for text processing and automation on the command line.
People Also Ask
How to use pipe in Bash script?
In Bash, the pipe operator (|) is used to create a ‘pipeline’ between commands. It takes the standard output (stdout) of the command to the left and pipes it as the standard input (stdin) to the command on the right. The basic syntax is: command_one | command_two
.
How to read a value in Bash?
To read a value in Bash. you can use the read command that takes the user input and splits the string into fields, assigning each new word to an argument. A common example of reading value with read
command is echo “Hello World” | { read name; echo “msg=$name”; }
. This will read the value from echo and pass it into the variable name.
How can I read line by line from a variable in Bash?
You can use a while loop
to read line by line from a variable in Bash. Let’s say you have a variable called data that stores multiple lines. Follow the script to read the lines one by one from a variable data:
while IFS= read -r line; do
echo "Line: $line"
done <<< "$data"
How to read input from file in Bash?
Let’s say you have a file called data.txt. To read input from a file in Bash, use this line in your script input_data=$(cat -)
. Then add your own processing logic. For example, if a Bash script (mybash.sh) contains the scripts:
input_data=$(cat -)
echo $input_data
Then executing the command cat data.txt | ./mybash.sh
will read the file data.txt and print it in the terminal.
Related Articles
- How to Pipe Output to File in Linux [4 Ways]
- Send Pipe Output to Two Commands in Bash [3 Methods]
- How to Use Double Pipe “||” in Bash [3 Examples]
<< Go Back to Bash Piping | Bash Redirection and Piping | Bash Scripting Tutorial