I'm not sure we have grasped the requirement here and I'm not sure if I understand it either, but I will have a go and you can tell me if I'm miles off the mark:-
whole_line=`head -1 $input_file`
data_portion="${whole_line##???}" # Get everything except first 3 chars
three_chars="${whole_line%$data_portion}" # Get everything except the data portion
target_file="header_bit${three_chars}trailer_bit" # Add anything required to build the target file name
echo $data_portion>$target_file # Chose overwrite or append carefully here
tail +2 $input_file > $tmp_file # Get record 2 and onward. 2 steps required
cat $tmp_file > $input_file # else you open $input_file for output
# before you have the data to write and
# you will null the file.
I coded the string chopping in ksh internal variable commands to avoid the overhead of starting processes (cut etc.) and the IO of writing to too many temporary files. If there is a neater way to remove a record from a file, I would like to know. I did toy with:-
echo "dd:wq" | vi $input_file
...but that can run in to problems if it is a large (wide) file or contains non-displayable data. It's a problem I get annoyed at a lot.
If you are thinking of writing a loop to process the whole file, you might be better to try one of these:-
for whole_line in `cat $input_file`
do
data_portion="${whole_line##???}" # Get everything except first 3 chars
three_chars="${whole_line%$data_portion}" # Get everything except the data portion
target_file="header_bit${three_chars}trailer_bit" # Add anything required to build the target file name
echo $data_portion >> $target_file # Always append or you only get the last match!
done
typeset -i counter=1
total_lines=`wc -l $input_file`
while [ $counter -le $total_lines]
do
whole_line=`sed -n ${counter}p $input_file`
data_portion="${whole_line##???}" # Get everything except first 3 chars
three_chars="${whole_line%$data_portion}" # Get everything except the data portion
target_file="header_bit${three_chars}trailer_bit" # Add anything required to build the target file name
echo $data_portion >> $target_file # Always append or you only get the last match!
((counter=$counter+1))
done
It could be sensible to truncate/remove the target files before you begin with these if you just want the output from this run. This is a neat way to acheive that:
for three_chars in `cut -c -3 $input_file|sort -u`
do
target_file="header_bit${three_chars}trailer_bit" # Add anything required to build the target file name
> $target_file # or substitute rm for the >
done
You could add
echo "$target_file $counter\r\c" >&2
... to get an overwriting line count as you progress. It will slow it down a bit but you should see the file name changing as the count runs. The "\r\c" will cause it to re-write the line with the next display.
There may also be a way to blend these all together
for three_chars in `cut -c -3 $input_file|sort -u`
do
target_file="header_bit${three_chars}trailer_bit" # Add anything required to build the target file name
for whole_line in `grep $three_chars $input_file`
do
data_portion="${whole_line##???}" # Get everything except first 3 chars
echo $data_portion
done > $target_file # Overwrite to negate the need to reset previous runs
done
This may give better performance from less IO and fewer processes, but perhaps the extereme could be
for three_chars in `cut -c -3 $input_file|sort -u`
do
target_file="header_bit${three_chars}trailer_bit" # Add anything required to build the target file name
grep $three_chars $input_file|cut -c 3- > $target_file
done
You would have to try out the variations to see which performs best given the variety of IO, spawned proceses etc.
I hope that this is somewhere near what you are after. Apologies if I've missed the point. Code has been raw typed, so there may be snytax errors I suppose, but have a go and let me know how you get on.
Robin
Blackburn/liverpool
UK