If you have many files, and most of those are valid, there is an efficient way to make a preliminary check. Just count the invalid characters: if there are none, there is no point making a more precise test of the file. We use tr
to remove the valid ones, and wc -c
to count the others.
More precise reporting is needed for the case where the count is non-zero.
I would suggest using awk, and defining the FS (field separator) as 'FS=[^ATGC]+', which means "any sequence of characters that are not A, T, G or C". If there are no incorrect characters on a line, then there will be only one field.
If more than one field exists, we can use the GNU/awk extension to split(), which provides the exact text of each field separator.
#! /bin/bash
Awk='
BEGIN { FS = "[^ATGC]+"; }
function Show (tx, Local, f, c, fTxt, fSep) {
split (tx, fTxt, FS, fSep)
for (f = 1; f in fSep; ++f) {
c += length (fTxt[f]);
printf ("File %s Line %d Column %d Has :%s:\n",
FILENAME, FNR, 1 + c, fSep[f]);
c += length (fSep[f]);
}
}
NF > 1 { Show( $0); }
'
for fn in q??; do
cc="$( tr -d 'ATGC\n' < "${fn}" | wc -c )"
(( cc == 0 )) && { echo "$fn is OK"; continue; }
awk "${Awk}" "${fn}"
done
and to test:
Paul--) head q??
==> q01 <==
TTGTAAGGTAAGTGGATTYTCCGGGRETC
TTVGGATCGTTGACCAGTK
GCCCGGGCCGGTCCTTTGGTGCGTGGGG
CTCTCCCAACCCCCCCACCCTCGACCTGAGCTCAGGCXC
BAACCCCZ
==> q02 <==
GCCCGGGCCGGTCCTTTGGTGCGTGGGG
==> q03 <==
TTGTAAGGTAAGTGGATTYTCCGGGRETC
Paul--)
Paul--) ./qFix q01 q02 q03
File q01 Line 1 Column 19 Has :Y:
File q01 Line 1 Column 26 Has :RE:
File q01 Line 2 Column 3 Has :V:
File q01 Line 2 Column 19 Has :K:
File q01 Line 4 Column 38 Has :X:
File q01 Line 5 Column 1 Has :B:
File q01 Line 5 Column 8 Has :Z:
q02 is OK
File q03 Line 1 Column 19 Has :Y:
File q03 Line 1 Column 26 Has :RE:
Paul--)