How to replace a line (directory path) with a variable containing another line (new directory path) in a Linux file? - linux

I have a file containing contents like:
aaaaaaaaaa
export ORACLE_HOME=/home/oracle/test/prod/db_1
bbbbbbbbbb
Now I want to replace the line of
export ORACLE_HOME=/home/oracle/test/prod/db_1
with something like below:
export ORACLE_HOME=/u01/app/oracle/product/11204/dbhome_1
I tried numerous ways found through Google like using "sed" or "awk" but neither one worked. I tried:
export D1="export ORACLE_HOME=/u01/app/oracle/product/11204/dbhome_1"
sed -i -e "s+export ORACLE_HOME=/home/oracle/test/prod/db_1+$D1+" file.lst
Note: as one Google search says, since the strings contains "/", so a different delimiter like "+" needs to be used.
Can you share with me the right command to do so?

sed -r 's~(ORACLE_HOME=).*~\1new/path/here~'
here ~ is used as the delimiter. If the new path is a bash variable, you can escape the quotes
sed -r 's~(ORACLE_HOME=).*~\1'$D1'~'

If you are still having trouble with the substitution, you can use this variation which will explicitly find the line containing export ORACLE_HOME before attempting the path substitution. The expression makes use of alternate delimiters for the substitution '|'.
To edit in place (Linux), you can use the '-i' option (and add '-i.bak' to make a backup of the original). If you are using a mac or other OS without the '-i' option available, use redirection to create a new file which you can copy over the current file.
sed -i '/^export\sORACLE_HOME/s|=.*$|=/u01/app/oracle/product/11204/dbhome_1|' \
yourfilename
or without '-i':
sed '/^export\sORACLE_HOME/s|=.*$|=/u01/app/oracle/product/11204/dbhome_1|' \
yourfilename > newfilename
cp yourfilename yourfilename.sav && mv -f newfilename yourfilename
(note: the '\' at the end of the sed command line is a simple line-continuation)
Using a Variable for Replacement
From your comment, if you want to use a variable instead of a hardcoded path for the replacement string, then simply replace the single-quotes with double-quotes and include the variable as the replacement string. For example:
npath=/u01/app/oracle/product/11204/dbhome_1
sed -i "/^export\sORACLE_HOME/s|=.*$|=$npath|" dat/opath.txt

Related

Using 'sed' to replace a string

I have a file that contains a URL and I wish to replace this URL with a new one.
This URL can be different each time so I do not wish to replace XXX with YYY but to change the value of a variable which contains the URL.
File looks like this:
APP_URL=https://test.hello.co/
I wish to change the value of APP_URL to a different URL but without success.
I am using a bash script in order to make this work.
tried using this inside my script and it didn't work.
oldline='APP_URL=https://test.hello.co'
newline='APP_URL=https://${variable}'
sudo sed -i 's/${oldline}/${newline}/g' .env
I would love to get help here!
Thank you :)
You need to remove the ' in sed and escape all / so that it doesn't think you are ending the part of s (or use other sign)
Both these work (my filename is .test):
variable=aaaaaaaaaaaaaaaaaaaaaaaaa
oldline='APP_URL=\S+'
newline='APP_URL=https:\/\/'$variable
sed -r s/${oldline}/${newline}/g .test
oldline='APP_URL=\S+'
newline='APP_URL=https://'$variable
sed -r s-${oldline}-${newline}-g .test
Single quotes prevent variable interpolation.
You can usually use double quotes instead.
$: cat tst
oldurl=test.hello.co
newurl=foo.bar.com
sed "s,APP_URL=https://${oldurl}/,APP_URL=https://${newurl}/,g" file
$: cat file
APP_URL=https://test.hello.co/
$: ./tst
APP_URL=https://foo.bar.com/
edit
Yes, this can be simplified a lot, such as by passing in the new url.
$: grep . tst file
tst:sed -E "s,APP_URL=https://[^/]+/,APP_URL=https://$1/,g" file
file:APP_URL=https://test.hello.co/
$: ./tst a.b.c
APP_URL=https://a.b.c/

Adding a new line to a growing paragraph using bash

I'm trying to write a bash script that adds a new line to a continually growing paragraph of a file. For every time I run the script it should add a new line to that paragraph but instead it returns the entire content of the file.
Here's my code...
function registerServiceProvider {
# register service provider inside config/app.php
sed '/App\Providers\*::class,/a \ App\Providers\${repoName}${provider}::class,' ./config/app.php
}
registerServiceProvider
By default sed prints the resulting stream to stdout. If you have GNU sed you can use -i to modify the file in-place. With many BSD sed you can use -i but it requires an argument which will be the extension added to the backup file created.
If you want to stay more POSIXy you can redirect the output to a new file, then move that temp file over the old name (or redirect the output to make sure you don't change the permissions). Don't try to do it with redirection in one step though, because the first thing the shell will do is truncate the file, then you'll try to read it and it will be empty.
So, with GNU sed you can do:
sed -i -e '/App\Providers\*::class,/a \ App\Providers\${repoName}${provider}::class,' ./config/app.php
or with BSD (or GNU, the argument works but is optional with GNU)
sed -i .bak -e '/App\Providers\*::class,/a \ App\Providers\${repoName}${provider}::class,' ./config/app.php
or portably
sed '/App\Providers\*::class,/a \ App\Providers\${repoName}${provider}::class,' ./config/app.php > tmp_paragraph
cat tmp_paragraph > ./config/app.php
rm tmp_paragraph
If you want the repoName and provider variables to be shell variables that get expanded you need to put the sed script in double quotes. bash doesn't expand variables inside single quoted strings. So to take the GNU sed example you would change it to use double quotes like so:
sed -i -e "/App\\\\Providers\\\\*::class,/a \\ App\\\\Providers\\\\${repoName}${provider}::class," ./config/app.php
and note that we had to do plenty of extra escaping of the slashes, since bash will treat them as escape characters inside double quotes. We can use the single quotes to help with that as long as we put the variables outside it though (and note that I'm still going to double the quotes because I think you meant to do that to get actual back slashes in those spots)
sed -i -e '/App\\Providers\\*::class,/a \ App\\Providers\\'${repoName}${provider}'::class,' ./config/app.php

difficult string to replace in script using SED

I know, many people have had questions on how to use sed to replace a string, but I have a difficult one here.
I have a file I need to replace a string of text that prompts the user to enter content. I want to automate this so the user does not interact. By replacing this string with a static file path. but the text is a bash script and has ' and " within the string I want to replace. It does not work. Either because I have syntax errors in my formatting, or it simply is not possible to do this action with sed. Please advice!
Here is what I am attempting to do:
I want to replace this long string
read -e -p 'Enter path for Boot Partition : ' BOOTUSERFILEPATH
with a string that looks like this:
BOOTUSERFILEPATH=../board-support/prebuilt-images
My attempt:
sed -i "/read -e -p 'Enter path for Boot Partition : ' BOOTUSERFILEPATH/BOOTUSERFILEPATH="../board-support/prebuilt-images"" file_to_search.sh
Update: I fixed the syntax error, but file still is not updated with the new path information... :(
found the problem. the search was not finding the strings because of an extra space in my search command. It works now!
There are forward slashes in your string so one needs to use a different delmiter. Here I use '|' as the delimiter.
sed "s|read -e -p \'Enter path for Boot Partition : \' BOOTUSERFILEPATH|BOOTUSERFILEPATH=../board-support/prebuilt-images|g" oldfile > newfile
You may note that the -i option to sed which allows files to be edited in place is not a POSIX supported option.
However if you wish to use it:
sed -i "s|read -e -p \'Enter path for Boot Partition : \' BOOTUSERFILEPATH|BOOTUSERFILEPATH=../board-support/prebuilt-images|g" oldfile
You may find it easier to use a pattern with sed which matches part of this string and then replaces its entirety:
sed 's|read -e -p .* BOOTUSERFILEPATH|BOOTUSERFILEPATH=../board-support/prebuilt-images|g' filename > newfilename
From the POSIX specification page for sed:
s/BRE/replacement/flags
Substitute the replacement string for instances of the BRE in the pattern space. Any character other than <backslash> or <newline> can be used instead of a slash to delimit the BRE and the replacement.
You need to use an actual substitute command, and you need to avoid the slashes in the replacement text from confusing sed. Personally, I'd probably use:
sed -i.bak "s%^read .* BOOTUSERFILEPATH$%BOOTUSERFILEPATH=../board-support/prebuilt-images%" file_to_search.sh
or even more likely:
BOOTUSERFILEPATH="../board-support/prebuild-images"
sed -i.bak "s%^read .* BOOTUSERFILEPATH$%BOOTUSERFILEPATH=$BOOTUSERFILEPATH%" file_to_search.sh
The s%%% uses % instead of / to delimit the parts of the command. I cheated on the match pattern, working on the assumption that you don't have many similar lines in the file.

How to remove line containing a specific string from file?

I have a file BookDB.txt which stores information in the following manner :
C++ for dummies:Jared:10.67:4:5
Java for dummies:David:10.45:3:6
PHP for dummies:Sarah:10.47:2:7
Assuming that during runtime, the scipt asks the user for the title he wants to delete. This is then stored in the TITLE variable. How do I then delete the line containing the string in question? I've tried the following command but to no avail :
sed '/$TITLE/' BookDB.txt >> /dev/null
You can for example do:
$ title="C++ for dummies"
$ sed -i "/$title/d" a
$ cat a
**Java for dummies**:David:10.45:3:6
**PHP for dummies**:Sarah:10.47:2:7
Note few things:
Double quotes in sed are needed to have you variable expanded. Otherwise, it will look for the fixed string "$title".
With -i you make in-place replacement, so that your file gets updated once sed has performed.
d is the way to indicate sed that you want to delete such matching line.
Your command should be,
sed "/$TITLE/d" file
To save the changes, you need to add -i inline edit parameter.
sed -i "/$TITLE/d" file
For variable expansion in sed, you need to put the code inside double quotes.

How to search and replace text in a file from a shell script?

I'm trying to write a shell script that does a search and replace inside a configuration file upon start-up.
The string we're trying to replace is:
include /etc/nginx/https.include;
and we want to replace it with a commented version:
#include /etc/nginx/https.include;
The file that contains the string that we want to replace is:
/etc/nginx/app-servers.include
I'm not a Linux guru and can't seem to find the command to do this.
perl -p -i -e 's%^(include /etc/nginx/https.include;)$%#$1%' /etc/nginx/ap-servers.include
If the line might not end in the ;, use instead:
perl -p -i -e 's%^(include /etc/nginx/https.include;.*)$%#$1%' /etc/nginx/ap-servers.include
If you want to preserve the original file, add a backup extension after -i:
perl -p -i.bak -e 's%^(include /etc/nginx/https.include;)$%#$1%' /etc/nginx/ap-servers.include
Now, explaining. The -p flag means replace in-place. All lines of the file will be fed to the expression, and the result will be used as replacement. The -i flag indicates the extension of the backup file. By using it without anything, you prevent generation of backups. The -e tells Perl to get the following parameter as an expression to be executed.
Now, the expression is s%something%other%. I use % instead of the more traditional / to avoid having to escape the slashes of the path. I use parenthesis in the expression and $1 in the substituted expression for safety -- if you change one, the other will follow. Thus, %#$1% is actually the second % of s, followed by the desired #, $1 indicating the pattern inside parenthesis, and the last % of s.
HTH. HAND.
sed -i 's/foo/bar/g' config.txt
This replaces all instances of foo (case insensitive) with bar in the file config.txt
Check out sed:
sed -i -r 's|^(include /etc/nginx/https.include;)$|#\1|' /etc/nginx/app-servers.include
-i means do the substitution in-place and -r means to use extended regular expressions.
cd pathname
for y in `ls *`;
do sed "s/ABCD/DCBA/g" $y > temp; mv temp $y;
done
This script shold replace string ABCD to DCBA in all the files in pathname

Resources