Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not able to replace String from file while iterating

The final.txt looks like:

build/create_changes.sh
build/create_changes.sh-meta.xml
src/aura/camping/camping.design
src/aura/camping/camping.design-meta.xml

I would like to replace only replace the files which contains /aura/ in its line to src/aura/camping

if [ -e final.txt ]
then
        ARRAY=()
        while read CFILE
            do
                    echo Analyzing file `basename $CFILE`
                    case "$CFILE"
                    in
                        *.design) TYPENAME="AuraDefinitionBundle";;
                        *) TYPENAME="UNKNOWN";;
                    esac

                    if [ "$TYPENAME" == "AuraDefinitionBundle" ]
                        then
                                if [ $(contains "${ARRAY[@]}" $(basename -- "$(dirname -- "$CFILE")")) != "y" ]
                                then
                                    echo baseFile from new method cFile $CFILE
                                    CFILENAME="$CFILE"

                                    replace="src/aura/"$(basename -- "$(dirname -- "$CFILE")")
                                    echo checkChanges "${CFILENAME/$CFILENAME/"$replace"}"
                                    CFILE="${CFILENAME/$CFILENAME/"$replace"}"
                                    echo baseFile from after change method cFile $CFILE
                                else
                                    continue
                                fi
                        fi
            done < final.txt
else
echo Change file not found!

This works, so I can see this in the window now:

 [exec] baseFile from new method cFile src/aura/camping/camping.design
 [exec] checkChanges src/aura/camping
 [exec] baseFile from after change method cFile src/aura/camping

But the file final.txt does not change:

build/create_changes.sh
build/create_changes.sh-meta.xml
src/aura/camping/camping.design
src/aura/camping/camping.design-meta.xml

I replaced it right there CFILE="${CFILENAME/$CFILENAME/"$replace"}"

Tried this too :

if [ $(contains "${ARRAY[@]}" $(basename -- "$(dirname -- "$CFILE")")) != "y" ]
then
    CFILENAME="$CFILE"
    ARRAY+=($(basename -- "$(dirname -- "$CFILE")"))
    replace="src/aura/"$(basename -- "$(dirname -- "$CFILE")")
    #CFILE="${CFILENAME/$CFILENAME/"$replace"}"
    sed -i 's/$CFILENAME/$replace/' final.txt
else
    continue
fi

Am I missing something more here?

like image 367
Nagendra Singh Avatar asked Mar 04 '26 22:03

Nagendra Singh


1 Answers

Your attempt has been good for the most parts, but the part involving changing the file content is incorrect in both the attempts.

Problem 1

You were surprised that the below attempt did not replace the contents of the file. It won't.

CFILE="${CFILENAME/$CFILENAME/"$replace"}"

Because the above is a bash internal construct for string replacement. It just replaces the string contents stored in the variable CFILENAME and puts the result to CFILE. No file modification is done at all.

Judging from your inputs your CFILENAME input would be src/aura/camping/camping.design and the replace variable would be src/aura/camping. Doing the above would put the string src/aura/camping to the variable CFILE and not to the file pointed by the variable CFILE.

Problem 2

You seemed to have identified that sed would solve your problem, which is in the right track, but you seemed to have missed a couple of tricks.

  1. You have variables defined in your sed search and replacement parts, but the problem is with the quotes. Variables in bash shell don't expand when single quoted but only with double-quotes.
  2. The next problem is with the de-limiter string used in sed, which is by default /. But remember both your source and replacement strings have / present, so sed would not understand what is the original and replacement text. You need to define a de-limiter that is not / and also any meta-character that is not part of your string. I would recommend | in your case

    sed "s|$CFILENAME|$replace|" final.txt
    
  3. Now the biggest problem is with the -i flag in your sed command which means in-place editing of your files whiles. Remember you are reading the file in a loop with a while read construct line by line and now your editing this file after parsing each line. You are messing up with the shell re-direction in a wrong way here. The ideal way would be re-direct your line by line edits to a temporary file and move it to your original file once the loop is done.

    sed "s|$CFILENAME|$replace|" final.txt >> temp_final.txt
    

Something like above using >> which appends to a file. And once the loop is finished, revert to your original file using mv

mv -- temp_final.txt final.txt
like image 140
Inian Avatar answered Mar 07 '26 23:03

Inian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!