Reputation: 41
I'm receiving input in the below format (emitting each bit in a bitfield as the individual digit that bit represents). I want to add those digits, to get the overall value for each field as a separate digit, as below. What is the best way to do it?
421 401 401
421 401 401
421 401 401
421 401 001
Output should be:
755
755
755
751
Upvotes: 0
Views: 107
Reputation: 15313
It's just loops. This doesn't confirm your input format, though you could.
while read -a bits # real the lines from your example
do for cnhk in "${bits[@]}" # walk through each group
do declare -i i=-1 tot=0 # initialize working vals
while (( ++i<${#chnk} )) # walk through the digits
do (( tot += ${chnk:$i:1} )) # total them
done
printf "$tot"; # print each digit
done
printf "\n" # newline after each set
done < datafile
If I understand what you're doing, you could as easily use symbolics, though your apparent expectations would make them all flat assignments and you lose most of the benefits...
declare -A prm=( [0]='' [1]=x [2]=w [4]=r )
declare -a ugo=( u g o )
while read -a bits
do sym=''
for chnk in 0 1 2
do sym="$sym,${ugo[$chnk]}="
for p in 4 2 1
do case "${bits[$chnk]}" in
*$p*) sym="$sym${prm[$p]}" ;;
esac
done
sym=${sym#,}
done
printf "%s\n" $sym
done < datafile
u=rwx,g=rx,o=rx
u=rwx,g=rx,o=rx
u=rwx,g=rx,o=rx
u=rwx,g=rx,o=x
Upvotes: 2
Reputation: 8711
Using Perl one-liner
$ cat adj_digits.txt
421 401 401
421 401 401
421 401 401
421 401 001
$ perl -pe ' s/(\S)/$1+/g; s/(\S+)/eval("$1 0")/ge;s/ //g ' adj_digits.txt
755
755
755
751
If you want to split and use @F, then
$ perl -lane ' for(@F) { $sum=0; $sum+=$_ for split(""); printf("%s",$sum); } print "" ' adj_digits.txt
755
755
755
751
Upvotes: 0
Reputation: 37414
Using GNU awk:
$ awk -v RS="[ \n]" '{
n=split($0,a,"") # separate chars into a array
for(i in a) # each array element
if(a[i]) # if >0
a[0]+=2^(n-i) # power and sum to a[0]
printf "%s%s",a[0],RT # output with stored separator
}' file
Output:
7 5 5
7 5 5
7 5 5
7 5 1
Upvotes: 0
Reputation: 189497
If you are asking how to sum adjacent digits in a text file, try
awk '{
# Loop over tokens on each line
for (i=1; i<=NF; ++i) {
# Is this token all numbers?
if ($i !~ /[^0-9]/) {
# Yes: Loop over numbers and sum them
sum = 0
for (j=1; j<=length($i); ++j)
sum += substr($i, j, 1)
# Finally replace the value with the sum
$i = sum
}
}
# Print every input line after possible substitutions
}1' filename.txt
Sample output:
7 5 5
7 5 5
7 5 5
7 5 1
The shell can read lines from a file and perform arithmetic on integers, but it's really not a good fit for this problem.
Upvotes: 4