1

I have a large file (>10000 lines) that contains one word per line, with a newline character after each word. The words contain no spaces.

I'd like to list (or even better, output to a new file) any words that start and/or end with a number, then I'd like to remove these from the original file. But I don't want to remove words that just contain numbers.

For example, if I had the contents

789
hello
1hello
112121hello3323
he11o
hello9
88888

Then the strings 1hello, 112121hello3323, hello9 would get output and then removed from the file.

How can I do this?

2

GNU grep

grep -vP '^\d+\D|\D\d+$'

produces

789
hello
he11o
88888
  • 1
    or POSIXly, grep -vE '^[[:digit:]]+[^[:digit:]]|[^[:digit:]][[:digit:]]+$' – iruvar Feb 9 '16 at 13:37
  • @1_CR Yeah i was going to add that but wasn't 100% that -E was completely posix compliant. – 123 Feb 9 '16 at 13:48
1

To actually edit the source file and create a new file with the discards is a bit trickier. I would do this

$ cat file
789
hello
1hello
112121hello3323
he11o
hello9
88888

$ perl -i -lne 'if (/^\d+\D|\D\d+$/) {warn "$_\n"} else {print}' file 2>file_nums

$ cat file
789
hello
he11o
88888

$ cat file_nums
1hello
112121hello3323
hello9

The matched lines are output on stderr, which is then redirected to a separate file. perl's -i flag takes care of saving the changes in-place.

The one-liner can be even trickier:

perl -i -lne 'print {/^\d+\D|\D\d+$/ ? STDERR : ARGVOUT} $_' file 2>file_nums
  • 1
    Note that this will also write any warnings or errors from perl into file_nums. – 123 Feb 9 '16 at 14:53
1

An awk solution:

awk '$0!~/.*[[:alpha:]][[:digit:]]+$/ && $0!~/^[[:digit:]]+[[:alpha:]]+/' words.txt
789
hello
he11o
88888

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.