5

I have the following file foo.txt:

1
AbcdJ
8192
Pak78
8291

I would like a bash script that extracts all the lines containing only integers (e.g. 1, 8192 but not AbcdJ or Pak78) and outputs it to bar.txt.

3 Answers 3

11

This extracts lines that contain only digits:

$ grep -E '^[[:digit:]]+$' foo.txt
1
8192
8291

This sends the output to bar.txt:

grep -E '^[[:digit:]]+$' foo.txt >bar.txt

How it works

When you want to select lines from a file, grep is first utility to try.

^[[:digit:]]+$ is a regular expression. In it, ^ matches the beginning of a line, [[:digit:]]+ matches one or more digits, and $ matches the end of a line. Because this regex starts with ^ and ends with $, it only matches whole lines. An alternative way of matching only whole lines is to use the -x option:

grep -xE '[[:digit:]]+' foo.txt >bar.txt

The option -E tells grep to use extended regular expressions. This reduces the need to escape things in the regex.

The > signifies redirection. It causes the output that would have appeared on the screen to go to a file named bar.txt.

2
  • 2
    You can also use the -x option to enforce a whole-line match (rather than using explicit ^ and $ anchors) grep -Ex '[[:digit:]]+' Jul 16, 2016 at 22:19
  • @steeldriver Good point. Answer updated with reference to -x.
    – John1024
    Jul 16, 2016 at 22:24
6

AWK solution:

$> cat input.txt
1
AbcdJ
8192
Pak78
8291
3 blind mice
$> awk '/^[[:digit:]]+$/' input.txt
1
8192
8291

Use > to redirect output to file

awk '/^[[:digit:]]+$/' input.txt > output.txt
2
  • sed -n '1p;3p;5p' will also print the integers from the foo.txt file given in the question, since they appear on the first, third, and fifth lines.  However, when a question says, "I have the following file," we generally interpret that to mean, "I have a file like the following..."  The question asks for a solution that extracts all the lines containing only integers.  Your answer will extract every line that begins with a digit; e.g., 3 blind mice.   P.S. When the question specifies filenames, it's nice to use those same filenames in your answer. Jul 16, 2016 at 23:16
  • @G-Man very valid point. The regex originally read as starting with digit and followed by zero or more matches of next char. I have corrected that to read line starting and followed by one or more matches of a digit , and included your example into the sample output. As for file naming, people may not be familiar with AWK syntax, hence i believe it is better to be explicit and state what is input file and what is output file. It is nice to use same names, but my goal is to make clear answer, not pretty ones. Jul 16, 2016 at 23:39
2

Some other tools:

  • sed:

    $ sed -n '/^[0-9]\+$/ p' foo.txt
    1
    8192
    8291
    
  • bash, slower than other approaches:

    $ while IFS= read -r line; do [[ $line =~ ^[0-9]+$ ]] && echo "$line"; done <foo.txt
    1
    8192
    8291
    

To save the output on another file, use output redirection, >:

sed -n '/^[0-9]\+$/ p' foo.txt >output.txt
while IFS= read -r line; do [[ $line =~ ^[0-9]+$ ]] && echo "$line"; done <foo.txt >output.txt

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .