sed replace two open brackets with a single one - sed

I have a file containing lines like
echo ((hello world))
I want the output to be
echo (hello world)
Any idea how I can accomplish this with sed?
sed 's/echo \(\(/echo \(\/' myfile
sed: -e expression #1, char 21: unterminated `s' command

You accidentally escaped the delimiter:
sed 's/echo \(\(/echo \(\/' myfile
^
I see you're not using sed -E, so it's better thet you drop all slashes as in BRE, brackets and braces shouldn't be escaped, as opposed to ERE. So the correct command would be (either of the two):
sed 's/echo ((/echo (/' myfile
sed -E 's/echo \(\(/echo \(/' myfile

Related

How to replace only specific spaces in a file using sed?

I have this content in a file where I want to replace spaces at certain positions with pipe symbol (|). I used sed for this, but it is replacing all the spaces in the string. But I don't want to replace the space for the 3rd and 4th string.
How to achieve this?
Input:
test test test test
My attempt:
sed -e 's/ /|/g file.txt
Expected Output:
test|test|test test
Actual Output:
test|test|test|test
sed 's/ /\
/3;y/\n / |/'
As newline cannot appear in a sed pattern space, you can change the third space to a newline, then change all newlines and spaces to spaces and pipes.
GNU sed can use \n in the replacement text:
sed 's/ /\n/3;y/\n / |/'
If the original input doesn't contain any pipe characters, you can do
sed -e 's/ /|/g' -e 's/|/ /3' file
to retain the third white space. Otherwise see other answers.
You could replace the 'first space' twice, e.g.
sed -e 's/ /|/' -e 's/ /|/' file.txt
Or, if you want to specify the positions (e.g. the 2nd and 1st spaces):
sed -e 's/ /|/2' -e 's/ /|/1' file.txt
Using GNU sed to replace the first and second one or more whitespace chunks:
sed -i -E 's/\s+/|/;s/\s+/|/' file
See the online demo.
Details
-i - inline replacements on
-E - POSIX ERE syntax enabled
s/\s+/|/ - replaces the first one or more whitespace chars
; - and then
s/\s+/|/ the second one or more whitespace chars on each line (if present).
Keep it simple and use awk, e.g. using any awk in any shell on every Unix box no matter what other characters your input contains:
$ awk '{for (i=1;i<NF;i++) sub(/ /,"|")} 1' file
test|test|test test
The above replaces all but the last " " on each line. If you want to replace a specific number, e.g. 2, then just change NF to 2.

Why is sed not matching excess whitespace between non-whitespace characters

I have a sed oneliner which removes excess whitespace:
sed -e 's/^\s*//' -e 's/\s*$//' -e 's/\s{2,}/ /g'
When I test it on " \tone1 two\t3three\t ", the sed removes the whitespace at the beginning and end of the line but doesn't match the excess whitespace between words, and sed returns \tone1 two\t3three. What I want is \tone1 two 3three, so sed -e 's/[ \t]{2,}/ /g' is not functioning.
regexr.com shows the expression as functional.
My version is GNU sed version 4.2.1.
{ and } need to be escaped in basic regex mode that sed uses.
However, you can use this sed with a single substitution with alternation:
sed -E 's/^[[:blank:]]+|[[:blank:]]+$|[[:blank:]]{2,}//g' file
POSIX character class [[:blank:]] matches a space or tab characters.

Delete line if string between the 4th and 5th delimiter is empty

"text";"text";"text";"text";;"text";"text"
If after the 4th delimiter the next one is following the line should be deleted.
Actually i'm doing that by using sed
sed -n '/;;/!p' input.txt
Is this a reliable solution?
Thanks for help.
Securing a bit potential escaped double quote and internal ";" (thanks #SLePort for remark)
sed -e 'h;s/\\"//g' -e ':c' -e 's/^\(\("[^"]*";\)*"[^"]*\);/\1/;t c' -e '/^\([^;]*;\)\{4\};/d;h'
sed -r '/^([^;]+;){4}\s*;/d' input.txt
awk -F';' '$5' input.txt
To remove lines containing ; after fourth delimiter:
sed '/^\("*[^"]*"*;\)\{4\};/d' input.txt
This might work for you (GNU sed):
sed -r '/^("(\\.|[^"])*";){4};/d' file
If the fourth grouping of double quotes followed by semi colon, where the characters within the grouping are either a pair of a quote and any other character or not a double quote, is followed by a further semi colon, then delete the line.
A more efficient regexp would be:
sed -r '/^("[^"\\]*(\\.[^"\\]*)*";){4};/d' file
This uses the pattern normal*(abnormal normal*)*

sed change line error message

I have a config file I need to change (again) and the line is
set wrapper_code=C:\windows\drivers\cache
I need to change it to
set wrapper_code=/home/harry/solo/run
I wrote
cat Proxy.bat | sed -i.bk -e 's/\(^set wrapper_home\=\).*/\/home/'1${dbuser}'/gateway/service\' Proxy.bat
I get an error message
sed: -e expression #1, char 37: unknown option to `s'
What is wrong with my code string
If you are using / as the pattern separator is sed, you have to escape the slashes in the strings (paths). To avoid it, use a different separator:
sed -i.bk -e 's%\^set wrapper_code=C:\\windows\\drivers\\cache%set wrapper_code=/home/harry/solo/run%' Proxy.bat
You also have to escape backslashes, as they have a special meaning in sed.
The cat part is useless.

About replacing string with sed

I'd like to replace all the \r\n with < br/ >in a document, and I'm trying this see script below
# sed -i 's/\r\n/<br/>' ~/xxd/*
however i got this error back
sed: -e expression #1, char 12: unknown option to `s'
How do i solve this problem?
Thanks!
Your problem is that you have the / separator in your replacement string so sed is assuming that's the end of your replacement, and that the > following it is a flag.
If your sed is modern enough, just use a different separator character, one that's not in the replacement string:
pax$ echo hello | sed -e 's/e/<br />/'
sed: -e expression #1, char 9: unknown option to `s'
pax$ echo hello | sed -e 's?e?<br />?'
h<br />llo
Alternatively, you can escape the offending character but I try to avoid that since it tends to lead to overly sawtooth sed commands like /\/\/\/\/\/\.
The other thing you may want to watch out for is trying to use \n in your regex since sed operates on lines anyway. If your intent is to just strip carriage returns and insert HTML line breaks, then the following sed command may be better:
s?\r$?<br />?