0

Let's assume I have the following text:

file.txt 4 minutes 11 seconds 102 msec
file_1.txt 5 minutes 10 seconds 100 msec
file_3_2.txt 0 minutes 10 seconds 100 msec

How do I delete all the words while retaining numbers and the filenames using sed?

file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100
0

4 Answers 4

0

There are multiple ways of extracting the data that you require.

If you see each line as a number of fields delimited by a space, then the most basic tool you could use to solve your issue would be cut:

$ cut -d ' ' -f 1,2,4,6 file
file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100

This extracts the 1st, 2nd, 4th, and 6th space-delimited field from the file.

Similarly, with awk:

$ awk '{ print $1,$2,$4,$6 }' file
file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100

This is doing the same thing, but there's slightly more going into it. The awk tool treats its input as a stream of records made up by fields. By default, a record is simply a line and a field is any non-blank text delimited by blanks (spaces or tabs, possibly more than one). The output is created, one record at a time (by default, a line at a time), and the fields are separated by a single space.


A slightly more involved approach would be to cut out the first field from the rest of the data, delete anything which is a letter in the rest of the data, and then paste the two together again.

$ paste -d ' ' \
    <( cut -d ' ' -f 1  file ) \
    <( cut -d ' ' -f 2- file | tr -s '[:alpha:]' '[ *]' )
file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100

This is a bit inelegant though, because it reads the input twice. The tr command used will change all alphabetical characters to spaces, and then "squeeze" (with -s) any set of multiple consecutive spaces down into single spaces.

The paste command gets two input streams and concatenates these line by line with a space character in-between them. The first stream is provided via a process substitution (<( ... )) running a cut command that extract only the first column from the data. The second stream is provided by another process substitution running cut to extract all columns from column 2 on, and which then replaces alphabetical characters with spaces in these columns using tr as just previously described.

2
  • Could you please explain in more detail the way your paste pipeline works?
    – Rubisko
    Commented May 9, 2021 at 1:42
  • @Rubisko See added bit at the end.
    – Kusalananda
    Commented May 9, 2021 at 6:23
0

It's unclear how specific your example is of your problem. Assuming it is literally what you are asking (which makes me worried it might be a class exercise) then you can take advantage of the fact that you have only 3 known strings to remove and that you want to end up with only single spaces between symbols to create a pretty short sed command. This example is using BSD sed supplied with MacOS, input is in the file input.txt and output is to stdout.

sed -E -e 's/ (minutes|seconds|msec)//g' < input.txt

This will match on a single space followed by one of your target strings and then replace it with nothing. The 'g' on the end says to apply repeatedly to the same line.

1
  • Thank you for your answer! My actual problem is a bunch of .out files with program execution times which look like this: CH3F_opt.out 0 days 0 hours 0 minutes 10 seconds 850 msec. As you see it is a bit longer, but still your suggestion works for me
    – Rubisko
    Commented May 9, 2021 at 1:38
0

Your problem can be tackled by the following GNU sed command:

$ sed -Ee ' /(\s+\S+)\s+\S+/\1/g' file

Where we keep alternating space-word and reject the next space-word combo.

0

One solution is to remove all "one space" followed by "non-numbers words":

$ sed -E 's/ \<[^0-9]*\>//g' file
file.txt 4 11 102
file_1.txt 5 10 100
file_3_2.txt 0 10 100

You must log in to answer this question.

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