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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .