1

I have long list of entries are recorded in a file, something like this short list:

FFF1B976-9DDE-11E7-9C3D-6241D7D553BE
682D9DB6-C0A2-11E8-B7A8-3ECB9C0CC049
682D9DB6-C0A2-11E8-B7A8-3ECB9C0CC049
6846DFEC-C0A2-11E8-B7A8-3ECB9C0CC049
6846DFEC-C0A2-11E8-B7A8-3ECB9C0CC049
--[SNIP]--

I want to filter this list based on the number of digits (characters in set 0123456789) within each entry and if the number of digits more than a specific threshold then keep the string otherwise remove it. in the previous example, how can I keep all the entries that have 18 digits in its names?

Expected output:

FFF1B976-9DDE-11E7-9C3D-6241D7D553BE
682D9DB6-C0A2-11E8-B7A8-3ECB9C0CC049
682D9DB6-C0A2-11E8-B7A8-3ECB9C0CC049
  • 2
    All of those have 32 digits; they just happen to be hexidecimal digits. – DopeGhoti Sep 28 '18 at 16:15
8

With awk:

awk -F '[[:digit:]]' 'NF > 18'

We use digits as the field separator, so the number of fields will be one plus the number of digits (x1y is split into x and y), so above we're looking for lines that have at least 18 digits.

(with mawk, replace [:digit:] with 0-9. mawk doesn't support POSIX character classes, but its [0-9] contrary to other awk implementations matches on 0123456789 only regardless of the locale. Portably, you can use [0123456789], or you can use [0-9] if you know the text doesn't contain non-ASCII data).

For lines that have exactly 18 digits, that would be:

awk -F '[[:digit:]]' 'NF == 19'

With sed, for at least 18 digits:

sed -e 's/[[:digit:]]/&/18;t' -e d

With grep:

grep -E '(.*[[:digit:]]){18}'
2

Let's say that the data are saved in a file called file.txt, then you can do something like:

#!/bin/bash
cat file.txt | while IFS= read line; do

n=$(echo $line | awk '{print gsub("[0-9]", "")}')
if [[ $n -gt 17 ]]; then 

echo $line
fi
done

FFF1B976-9DDE-11E7-9C3D-6241D7D553BE
682D9DB6-C0A2-11E8-B7A8-3ECB9C0CC049
682D9DB6-C0A2-11E8-B7A8-3ECB9C0CC049

Or

awk 'gsub("[0-9]", "&") >= 18'
  • or, more directly, awk '{if (gsub("[0-9]", "") > 17) print;}' < file.txt – Jeff Schaller Sep 28 '18 at 16:20
  • 3
    @JeffSchaller, you'd want awk 'gsub("[0-9]", "&") >= 18' instead. – Stéphane Chazelas Sep 28 '18 at 16:21
  • @Jeff Schaller I really don't know, this is what come to mind, very old style ;-) – user88036 Sep 28 '18 at 16:24
  • Or awk 'split($0,a,/[0-9]/)>18' – Isaac Sep 29 '18 at 4:09
1

To find lines with 18 digits ([0-9]) and more, you can use grep.

egrep '([0-9][^0-9]*){18}'

or

grep -E '([0-9][^0-9]*){18}'

Description

egrep is same as grep -E.

grep      # Command to filter text using regular expressions
-E        # Use extended regex

(
  [0-9]   # Exactly one digit
  [^0-9]* # 0 or more characters except digits
)           
{18}      # Find 18 times
  • 2
    This only finds consecutive digits. – David Conrad Sep 28 '18 at 21:15
  • @DavidConrad Yes, I was wrong. – jiwopene Sep 30 '18 at 9:37
  • It should be OK now. – jiwopene Sep 30 '18 at 9:38
0

How about using the return value of perl's tr (similar to using the returnvalue of awk's gsub)

$ perl -ne 'print if tr{0-9}{0-9} >= 18' file
FFF1B976-9DDE-11E7-9C3D-6241D7D553BE
682D9DB6-C0A2-11E8-B7A8-3ECB9C0CC049
682D9DB6-C0A2-11E8-B7A8-3ECB9C0CC049

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.