dd can pad newline-terminated records to appropriate lengths with spaces, but they must be newline-terminated. Here is a utility to convert to newline-terminated records:
// convert to an executable with cc block.c -o block
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
long int BLOCK=0;
char *buf=NULL;
if(argc < 2)
{
fprintf(stderr, "usage: %s blocksize [inputfile]\n", argv[0]);
exit(1);
}
if(argc >= 2) BLOCK=strtol(argv[1], NULL, 10);
if(argc >= 3) {
if(freopen(argv[2], "rb", stdin)==NULL)
{
perror("Couldn't open");
return(1);
}
}
if(BLOCK<=0)
{
fprintf(stderr, "Invalid block size %ld\n", BLOCK);
return(1);
}
buf=malloc(BLOCK+1);
if(buf == NULL)
{
perror("Couldn't allocate");
return(1);
}
// fprintf(stderr, "block size %ld\n", BLOCK);
buf[BLOCK]='\n';
while(fread(buf,BLOCK,1,stdin))
fwrite(buf,BLOCK+1,1,stdout);
free(buf);
return(0);
}
Having done that, you can convert it with iconv, pad to the required length with dd, then remove the newlines with tr.
In my example, I delete capital letters from aAabBbcccdDdeeEfffggghhhiIijjjkkklLlmmmnnn
without changing length.
#!/bin/sh
BLOCKSIZE=3
# Add newlines using block utility
./block $BLOCKSIZE |
# Remove characters, i.e. you'd put iconv here
tr -d 'A-Z' |
# Pad shrunken records with spaces
dd ibs=$BLOCKSIZE cbs=$BLOCKSIZE conv=sync,block 2>/dev/null |
# Remove newlines
tr -d '\n'
$ cat fixed.txt
aAabBbcccdDdeeEfffggghhhiIijjjkkklLlmmmnnn
$ ./dump.sh < fixed.txt
aa bb cccdd ee fffggghhhii jjjkkkll mmmnnn
$
You end up with one blank record at the end, full of spaces, which I haven't figured out how to avoid yet.