I process a text file with many domain like
abcd.efgh.ijkl.mnop
I hope to add a 3 at the same line no matter how it is at the beginning or at the end.
current I use
sed 's/[^.]//g' thetextfile | awk '{ print length }' > thenumber
then I use librecalc to combine them.
In plain bash
, without using any external utility:
#!/bin/bash
while read -r line; do
dots=${line//[^.]}
printf '%d\t%s\n' ${#dots} "$line"
done < file
Using a perl one-liner, taking advantage of tr
returning the number of changes:
$ perl -ne 'print tr/././, " ", $_' input.txt
3 abcd.efgh.ijkl.mnop
6 abcd.efgh.ijkl.mnop...
4 abcd.efgh.ijkl.mnop.
The blindingly obvious answer is
awk -F . '{ print NF-1, $0 }' thetextfile >thenumber
Combining the results to a single file in an external utility seems like a humongous overcomplication; just process all the files in one go.
awk -F . '{ print NF-1, $0 }' * >allnumbers
or if your needs are more complex maybe something like
for file in *.txt; do
echo "$0: processing $file ..." >&2
awk -F . '{ print NF-1, $0 }' "$file"
done >allnumbers
The -F .
says to use the literal dot as field separator, and NF
is the number of fields (which will be one more than the number of separators; look up “fencepost error” if you don’t understand why).
In more complex cases still, maybe append the output from each file with >>allnumbers
inside the loop if you really need to (but understand that this is less efficient than only writing once after the done
).
Awk’s default output field separator is a single space; if you want to produce TSV (tab-separated output) or CSV, you can set OFS="\t"
or OFS=","
as required.