Replace string pattern having space and line feeds using sed - unix

Below I am setting a variable read from a file:
$ replace=$(cat file.txt)
and I am trying to use sed as below
$ sed -i 's|old|'$replace'|g'
However, I get the below error:
sed: -e expression #1, char 7: unterminated `s' command
Note - In my case the replace string is read from a file which has space and line feed like below.
file.txt
line 1
line 2
Can't sed handle patterns that have new lines?

Is it possible? Probably though maybe with some non-portable GNU extensions but it's not what sed is for anyway (simple substitutions on individual lines) so don't do it with sed, just use awk:
awk 'NR==FNR{new = new $0 ORS; next} {sub(/old/,new)}1' file.txt targetFile
Note you don't need a shell variable with cat to do it but you can use one if you like:
replace=$(cat file.txt)
awk -v new="$replace" '{sub(/old/,new)}1' targetFile

Related

Combine two sed commands in one line

I'm looking for an in place command to change all file lines which end with :.:.
From
chr01 1453173 . C T 655.85 PASS . GT:AD:DP:PGT:PID 0/1:25,29:54:.:.
To
chr01 1453173 . C T 655.85 PASS . GT:AD:DP 0/1:25,29:54
In words, I'm basically deleting :PGT:PID and :.:. from any line ending with :.:.
With GNU sed and Solaris sed:
sed '/:\.:\.$/{s///;s/PGT:PID//;}' file
If you want to edit your file with GNU sed "in place" use option -i.
With awk that'd be:
awk 'sub(/:\.:\.$/,""){sub(/:PGT:PID/,"")} 1' file
chr01 1453173 . C T 655.85 PASS . GT:AD:DP 0/1:25,29:54
and for inplace editing with gawk you could add the -i inplace option while with any awk you can just add > tmp && mv tmp file.
You are looking for something like:
sed -i.bak "/^.*:\.:\.$/ {s/:PGT:PID//g; s/:\.:\.//g;}" file
it does inplace replace with file and creates a backup as file.bak
the /^.*:\.:\.$/ restricts the s command to lines ending in :.:. the . need quoting because they are special characters for regexes
the s sommand replaces the strings with the empty string
As a one-liner:
sed -i -e '/:\.:\.$/!n' -e 's///' -e 's/:PGT:PID//g' "$file"
Expanded:
/:\.:\.$/!n # leave lines untouched unless they end in ":.:."
s/// # replace the matched ":.:." with nothing
s/:PGT:PID//g # replace ":PGT:PID" with nothing, everywhere
We use the -i flag to perform in-place edits. We pass each line as a separate -e expression for portability: some sed implementations allow several commands to be concatenated with ;, but that is not required by the POSIX standard.

SED substitute from variable containing special characters

I want to use SED in order to substitute a placeholder (##ERROR_MSG##) contained in a .txt file with the content of a variable ($ERROR_MSG)
here the command I use:
cat FILE.TXT | sed "s/##ERROR_MSG##/$ERROR_MSG/"
here what is contained in $ERROR_MSG (contains special characters and is multi line)
ERROR:
ORA-12170: TNS:Connect timeout occurred
ERROR:
ORA-12162: TNS:net service name is incorrectly specified
SP2-0306: Invalid option.
Usage: CONN[ECT] [{logon|/|proxy} [AS {SYSDBA|SYSOPER|SYSASM}] [edition=value]] where <logon> ::= <username>[/<password>][#<connect_identifier>]
<proxy> ::= <proxyuser>[<username>][/<password>][#<connect_identifier>]
SP2-0157: unable to CONNECT to ORACLE after 3 attempts, exiting SQL*Plus
I recieve the following error message:
sed: -e expression #1, char 22: unterminated `s' command
The only robust way to do this, which will work with any value of $ERROR_MSG is:
awk -v old="##ERROR_MSG##" -v new="$ERROR_MSG" 's=index($0,old){$0 = substr($0,1,s) new substr($0,s+length(old))} 1' file
try this:
sed "s+##ERROR_MSG##+$ERROR_MSG+" FILE.TXT
your line didn't work because the text in $ERROR_MSG contains slash /.
edit:
try this awk oneliner too:
awk -v t="$ERROR_MSG" '{sub(/##ERROR_MSG##/,t)}7' FILE.TXT

using sed -n with variables

I am having a log file a.log and i need to extract a piece of information from it.
To locate the start and end line numbers of the pattern i am using the following.
start=$(sed -n '/1112/=' file9 | head -1)
end=$(sed -n '/true/=' file9 | head -1)
i need to use the variables (start,end) in the following command:
sed -n '16q;12,15p' orig-data-file > new-file
so that the above command appears something like:
sed -n '($end+1)q;$start,$end'p orig-data-file > new-file
I am unable to replace the line numbers with the variables. Please suggest the correct syntax.
Thanks,
Rosy
When I realized how to do it, I was looking for anyway to get line number into a file containing the requested info, and display the file from that line to EOF.
So, this was my way.
with
PATTERN="pattern"
INPUT_FILE="file1"
OUTPUT_FILE="file2"
line number of first match of $PATTERN into $INPUT_FILE can be retrieved with
LINE=`grep -n ${PATTERN} ${INPUT_FILE} | awk -F':' '{ print $1 }' | head -n 1`
and the outfile will be the text from that $LINE to EOF. This way:
sed -n ${LINE},\$p ${INPUT_FILE} > ${OUTPUT_FILE}
The point here, is the way how can variables be used with command sed -n:
first witout using variables
sed -n 'N,$p' <file name>
using variables
LINE=<N>; sed -n ${LINE},\$p <file name>
Remove the single quotes thus. Single quotes turn off the shell parsing of the string. You need shell parsing to do the variable string replacements.
sed -n '('$end'+1)q;'$start','$end''p orig-data-file > new-file

find and replace from command line unix

I have a multi line text file where each line has the format
..... Game #29832: ......
I want to append the character '1' to each number on each line (which is different on every line), does anyone know of a way to do this from the command line?
Thanks
sed -i -e 's/Game #[0-9]*/&1/' file
-i is for in-place editing, and & means whatever matched from the pattern. If you don't want to overwrite the file, omit the -i flag.
Using sed:
cat file | sed -e 's/\(Game #[0-9]*\)/\11/'
sed 's/ Game #\([0-9]*\):/ Game #1\1:/' yourfile.txt
GNU awk
awk '{b=gensub(/(Game #[0-9]+)/ ,"\\11","g",$0); print b }' file

How do I replace a token with the result of `pwd` in sed?

I'm trying to do something like this:
sed 's/#REPLACE-WITH-PATH/'`pwd`'/'
Unfortunately, I that errors out:
sed: -e expression #1, char 23: unknown option to `s'
Why does this happen?
You need to use a different character instead of /, eg.:
sed 's?#REPLACE-WITH-PATH?'`pwd`'?'
because / appears in the pwd output.
in sed, you can't use / directly, you must use '/'.
#!/bin/bash
dir=$`pwd`/
ls -1 | sed "s/^/${dir//\//\\/}/g"
sed 's:#REPLACE-WITH-PATH:'`pwd`':' config.ini
The problem is one of escaping the output of pwd correctly. Fortunately, as in vim, sed supports using a different delimiter character. In this case, using the colon instead of slash as a delimiter avoids the escaping problem.
instead of fumbling around with quotes like that, you can do it like this
#!/bin/bash
p=`pwd`
# pass the variable p to awk
awk -v p="$p" '$0~p{ gsub("REPLACE-WITH-PATH",p) }1' file >temp
mv temp file
or just bash
p=`pwd`
while read line
do
line=${line/REPLACE-WITH-PATH/$p}
echo $line
done < file > temp
mv temp file

Resources