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.
Related
I have to find and replace all the occurrence of a string in all files /eOffice/eofficev6 to /eOffice/SAPS/eofficev6 recursively in a directory in RHEL 7.4.
Problem is that I using sed -i but my string also containing / slash.
How to replace all string having /?
You have two ways to achieve what you want.
One: Escape slashes (E.G. sed -i "s/\/eOffice\/eofficev6/\/eOffice\/SAPS\/eofficev6/" file).
Two: change the delimiter (E.G. sed -i "s|/eOffice/eofficev6|/eOffice/SAPS/eofficev6|" file).
You could do
sed -i 's/\(\/eOffice\)\(\/eofficev6\)/\1\/SAPS\2/' input_file_name
The "/eOffice" and "eofficev6" parts are grouped and the "SAPS" is inserted in between.
For example, if the input is:
/eOffice/eofficev6
the output will be
/eOffice/SAPS/eofficev6
Forward slashes are escaped with \s.
Or without grouping just,
sed -i 's/\/eOffice\/eOfficev6/\/eOffice\/SAPS\/eOfficeb6/' input_file
I have a file withe following data
:1:aaaaa:aaa:aaa
and i want to remove the leading colon using bash to be like
1:aaaaa:aaa:aaa
You could use sed:
sed 's/^://' filename
^ denotes the start of line, so ^: would match a colon at the beginning of a line. Replace it by nothing!
str=':1:aaaaa:aaa:aaa'
echo ${str:1} #=> 1:aaaaa:aaa:aaa
Resources: Bash string manipulation
As well as sed, you may get better performance for such a simple operation on a large file by using cut:
cut myfile -d : -f 2-
You can also extract additional fields this way with other -f values.
If you want to remove the leading colon from data in a variable, such as in a loop, you can also do
myvar=":1:aaaaa:aaa:aaa"
echo ${myvar#:}
I've read lots of posts to understand how to correctly escape white spaces and special characters inside strings using sed, but still i can't make it, here's what i'm trying to achieve.
I have a file containing the some strings like this one:
JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.jsessionid=some_value"
and i'm trying to replace 'some_value' using the following:
sed -i "s/^\(JAVA_OPTS=\"\$JAVA_OPTS[ \t]*-Dorg\.apache\.catalina\.jsessionid*=\s*\).*\$/\1$DORG_APACHE_CATALINA_JSESSIONID/" $JBOSS_CONFIGURATION/jboss.configuration
$JBOSS_CONFIGURATION is a variable containing an absolute Linux path.
jboss.configuration is a file i'm pointing as the target for replace
operations.
$DORG_APACHE_CATALINA_JSESSIONID contains the value i want instead
of 'some_value'.
Please note that the pattern:
JAVA_OPTS="$JAVA_OPTS -D
Is always present, and org.apache.catalina.jsessionid is an example of a variable value i'm trying to replace with this script.
What's missing/wrong ? i tried also escaping whitespaces using \s without success,
and echoing the whole gives me the following:
echo "s/^\(JAVA_OPTS=\"\$JAVA_OPTS[ \t]*-Dorg\.apache\.catalina\.jsessionid*=\s*\).*\$/\1$DORG_APACHE_CATALINA_JSESSIONID/"
s/^\(JAVA_OPTS="$JAVA_OPTS[ \t]*-Dorg\.apache\.catalina\.jsessionid*=\s*\).*$/\1/
is echo interpreting the search pattern as sed does ?
any info/help/alternative ways of doing it are highly welcome,
thank you all
echo 'JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.jsessionid=some_value"' | (export DORG_APACHE_CATALINA_JSESSIONID=FOO/BAR/FOOBAR; sed "s/^\(JAVA_OPTS=\"\$JAVA_OPTS[ \t]*-Dorg\.apache\.catalina\.jsessionid*=\s*\).*\$/\1${DORG_APACHE_CATALINA_JSESSIONID////\/}\"/")
Note the bash expansion (in order to escape any / that may trip up sed) and the extra \" after $DORG_APACHE_CATALINA_JSESSIONID in order to properly close the double quote. Other than that your sed expression works for me and the above command outputs the follwoing result:
JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.jsessionid=FOO/BAR/FOOBAR"
You can use sed like this:
sed -r '/\$JAVA_OPTS -D/{s/^(.+=).*$/\1'"$DORG_APACHE_CATALINA_JSESSIONID"'/;}' $JBOSS_CONFIGURATION/jboss.configuration
You can specify a pattern that'll match the desired string rather than trying to specify it exactly.
The following should work for you:
sed -i 's#^\(JAVA_OPTS.*Dorg.apache.catalina.jsessionid\)=\([^"]*\)"#\1='"$DORG_APACHE_CATALINA_JSESSIONID"'"#' $JBOSS_CONFIGURATION/jboss.configuration
sed 's/=\w.*$/='"$DORG_APACHE_CATALINA_JSESSIONID"'/' $JBOSS_CONFIGURATION/jboss.configuration
I am using sed -e "s/foo/$bar/" -e "s/some/$text/" file.whatever to replace a phrase in a certain file. The problem is that the $bar string contains multiple special characters like /. So when I try to replace something in a text file using the following code...
#!/bin/bash
bar="http://stackoverflow.com/"
sed -e "s/foo/$bar/" -e "s/some/$text/ file.whatever
...then I get an error saying : sed: unknown option to s is there anything I can do about it?
You can use any delimiter. s#some#SOME# for example. Another good delimiter is vertical-bar. Other chars can work but have special significance for some contexts such as regular expressions.
You can get this difficulty in sed regardless of what delimiters you use, especially if you don't know what the string contains. I'd pick a different method for passing the shell variables into the helper interpreter.
awk -v rep1="$bar" -v rep2="$text" '{sub(/foo/, rep1); sub(/some/, rep2); print}'
or
perl -spe 's/foo/$rep1/; s/some/$rep2/' -- -rep1="$bar" -rep2="$text"
Correctness trumps brevity in this case.
(reference for Perl example)
In my project.pro file I have:
DEFINES += VERSION=\\\"1.13.1\\\"
I'd like to replace whatever the current version number is, with a new one in a Bash script:
VERSION_MAJOR=1
VERSION_MINOR=14
VERSION_PATCH=1
sed -i "s/\([0-9]+.[0-9]+.[0-9]+\)/\1${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}/" project.pro
Why is that not working?
So far I have managed to get either no matches at all or then some weird replace-only-the-last-number substitutions.
You may use this sed:
sed -i.bak -E "s/[0-9]+\.[0-9]+\.[0-9]+/$VERSION_MAJOR.$VERSION_MINOR.$VERSION_PATCH/" project.pro
Few problems in your attempt:
Without extended regex mode (-E), + cannot be used unescaped.
dot needs to be escaped in a regex
No need to use a capture group and back-reference \1.
PS: .bak is extension of backup file so that you can get original file, in case of a wrong substitution.