3

I'm writing a script which should copy a client system and change some lines in a file.

There is a source file which has a line like:

$DB_HOST = "LegitDbHost";

And the destination file has a line like:

$DB_HOST = "testDbHost";

So i need to replace the destination line with the source line and I want to print out something like this:

Replacing line 12: '$DB_HOST = "testDbHost";' ==with==> '$DB_HOST = "LegitDbHost";'(y/n): 

So far i got this:

toReplace='$DB_HOST';

sourceLine=$(cat ./sourceFile.php | grep -m 1 "$toReplace[[:space:],=]");
destLineNr=$(cat ./destFile.php | grep -n -m 1 "$toReplace[[:space:],=]" | grep -Eo '^[^:]+');
destLine=$(cat ./destFile.php | grep -m 1 "$toReplace[[:space:],=]");
read -p "Replacing line $destLineNr: $destLine ==with==> $sourceLine.(y/n): ";

however, my output looks like this:

==with==> $DB_HOST    ST   = "testDbHost";.(y/n): 

I think it's because the sourceLine has a ; inside and that gets interpreted as a command end. I just don't know how to get around that.

I hope it's understandable.

Edit: as suggested i tried using echo -n

toReplace='$DB_HOST';

sourceLine=$(cat ./sourceFile.php | grep -m 1 "$toReplace[[:space:],=]");
destLineNr=$(cat ./destFile.php | grep -n -m 1 "$toReplace[[:space:],=]" | grep -Eo '^[^:]+');
destLine=$(cat ./destFile.php | grep -m 1 "$toReplace[[:space:],=]");

echo -n "Replacing line $destLineNr: "
echo -n $destLine
echo -n " ===with===> "
echo -n $sourceLine

this prints out:

===with===> $DB_HOST = "testDbHost";OS";
5
  • 3
    It sounds more like your problem has to do with your files having Microsoft DOS/Windows CRLF line delimiters. You may want to run dos2unix on them first. Feb 20, 2021 at 10:11
  • Why not just echo your string with the variable substitutions (optionally with the -n flag to prevent a terminal newline being appended) and then call read -p '(y/n)?' as the next command in the script? That should accomplish what you desire, if I'm understanding it correctly. Feb 20, 2021 at 10:59
  • tried echo -n. See my edit. Also tried dos2unix, but it's not installed on the system and I don't have permissions to do so.
    – Pascal
    Feb 20, 2021 at 12:04
  • To check whether it is as @StéphaneChazelas says use hd or od to just dump a specific line and show output. eg. grep DB_HOST sourceFile.php|hd repeat with destFile.php if you haven't got hd use od -cbx --endian big (btw, your code works for me using bash)
    – X Tian
    Feb 20, 2021 at 12:31
  • On detecting and removing carriage return characters: unix.stackexchange.com/q/79702/315749 and unix.stackexchange.com/q/32001/315749
    – fra-san
    Feb 20, 2021 at 12:53

1 Answer 1

0

Try:

#! /bin/zsh -
die() {
  print -ru2 -- "$@"
  exit 1
}

srcFile=./sourceFile.php
dstFile=./destFile.php

toReplace='$DB_HOST'

sourceLine=$(<"$srcFile" grep -Pm1 "\Q$toReplace\E[\s,=]") ||
  die "Can't find $toReplace in $srcFile"

<"$dstFile" grep -nPm 1 "\Q$toReplace\W[\s,=]" |
  IFS=: read -r destLineNr destLine ||
  die "Can't find $toReplace in $dstFile"

if
  read -q "?Replacing line $destLineNr: ${(q+)destLine} ==with==> ${(q+)sourceLine}? (y/n): "
then
  (
     export destLineNr destLine
     perl -lpi -e '$_ = $ENV{destLine} if $. == $ENV{destLineNr}' -- "$dstFile"
  )
fi

Using ${(q+)line} zsh parameter expansion, will make sure CR characters in that variable (as it looks like your input files have MSDOS CRLF delimiters instead of Unix LF ones) is rendered as C-M instead of being sent as-is to the terminal (for a terminal, a CR character makes the cursor go back to the beginning of the line (makes the carriage return for teletypewriter ones)).

4
  • getting this now: Warning: unknown mime-type for "-ru2" -- using "application/octet-stream" Error: no such file "-ru2" Error: no such file "Can't find $DB_HOST in ./destFile.php"
    – Pascal
    Feb 20, 2021 at 14:10
  • i have to mention that I'm a total beginner in terms of bash scripting. I got this task from my company, just started to google some commands yesterday.
    – Pascal
    Feb 20, 2021 at 14:11
  • @Pascal, that's a zsh script not a bash script (note the shebang). Either make it executable with chmod a+x that-script and run it as ./that-script or run it as zsh ./that-script, not bash ./that-script. Feb 20, 2021 at 15:32
  • tried. it says: -bash: zsh: command not found
    – Pascal
    Feb 20, 2021 at 15:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.