The problem is that when creating the array, you separate the string into several elements (one containing the O
, another containing 331
, etc.), but the spaces are lost. When trying to print the array again, he has no way of knowing how many spaces they had previously (he will only print the elements, separating them by a space).
An alternative is not to break the string into an array, and extract only the snippet you want and replace it:
#!/bin/bash
STR="O 331 RATO ROEU A ROUPA 68.352 47.294 40.713 1.00 16.48 C"
VAL=$(echo "$STR" | awk '{print $2}')
if [ $VAL -gt 99 ] && [ $VAL -lt 999 ]
then
STR=$(echo "$STR" | sed "s/${VAL}/ 1/")
fi
echo "$STR"
The awk
breaks the string into multiple parts, separated by space, and allows you to manipulate them the way you need to. In case I’m only taking the second part (print $2
), which corresponds to the 331
.
Then I test the value of this and do the substitution in the original string, using sed
, that changes the value 331
number 1 with multiple spaces before. Finally, just print the string. The result is:
O 1 RATO ROEU A ROUPA 68.352 47.294 40.713 1.00 16.48 C
Note that the sed
replaced the 331
for "1 with multiple spaces before". But if you just want to exchange 331 for 1 and keep the same amount of spaces, just do:
STR=$(echo "$STR" | sed "s/${VAL}/1/")
Another way to do it is to use grep
to pick up either the spaces, or one of the "words" (anything other than space), and go concatenating the resulting strings (replacing only the one you need):
STR="O 331 RATO ROEU A ROUPA 68.352 47.294 40.713 1.00 16.48 C"
IFS=$'\n'
RES=""
i=1
for s in $(echo "$STR" | grep -oE ' +|[^ ]+')
do
if [ $i -eq 3 ] && [ $s -gt 99 ] && [ $s -lt 999 ]
then
s='1'
fi
RES="$RES$s"
i=$((i+1))
done
echo "$RES"
The grep
uses regular expression ' +|[^ ]+'
(one or more spaces or one or more characters that are not spaces), and returns each of these passages separately (first the O
, then the spaces, then the 331, the spaces, etc).
The for
goes through those results, but I had to change the IFS
for him to consider the line break (\n
) as separator, so the for
also considers spaces as elements when iterating through results.
Within the for
I replace only the field I want, and the rest remains the same (including spaces), and I concatenate everything into the variable RES
.
The result is the same:
O 1 RATO ROEU A ROUPA 68.352 47.294 40.713 1.00 16.48 C