Search code examples
bashshellawksedecho

How to add a space after special characters in bash script?


I have a text file with something like,

!aa
@bb
#cc
$dd
%ee

expected output is,

! aa
@ bb
# cc
$ dd
% ee

What I have tried, echo "${foo//@/@ }".

This does work fine with one string but it does not work for all the lines in the file. I have tried with this while loop to read all the lines of the file and do the same using echo but it does not work.

while IFS= read -r line; do
    foo=$line
    sep="!@#$%"
    echo "${foo//$sep/$sep }"
done < $1

I have tried with awk split but it does not give the expected output. Is there any workaround for this? by using awk or sed.


Solution

  • The following assumes you want to add a space after every character in the !@#$% set (even if it is the last character in a line). Test file:

    $ cat file.txt
    a!a
    @bb
    c#c
    $dd
    ee%
    foo
    %b%r
    $ sep='!@#$%'
    

    With sed:

    $ sed 's/['"$sep"']/& /g' file.txt
    a! a
    @ bb
    c# c
    $ dd
    ee% 
    foo
    % b% r
    

    With awk:

    $ awk '{gsub(/['"$sep"']/,"& "); print}' file.txt
    a! a
    @ bb
    c# c
    $ dd
    ee% 
    foo
    % b% r
    

    With plain bash (not recommended, it is too slow):

    $ while IFS= read -r line; do
        str=""
        for (( i=0; i<${#line}; i++ )); do
          char="${line:i:1}"      
          str="$str$char"
          [[ "$char" =~ [$sep] ]] && str="$str "
        done
        printf '%s\n' "$str"
      done < file.txt
    a! a
    @ bb
    c# c
    $ dd
    ee% 
    foo
    % b% r
    

    Or (not sure which is the worst):

    $ while IFS= read -r line; do
        for (( i=0; i<${#sep}; i++ )); do
          char="${sep:i:1}"
          line="${line//$char/$char }"
        done
        printf '%s\n' "$line"
      done < file.txt
    a! a
    @ bb
    c# c
    $ dd
    ee% 
    foo
    % b% r