apply sed command only if no dot before - sed

My sed command does not work as expected.
sed -E ':a;N;$!ba;s/[^\.](\[[0-9]]) \n\n/\1 /g'
I want this :
blabla[3]
foofoo
barbar.[4]
blabla
To become :
blabla[3] foofoo
barbar.[4]
blabla
That is, I just want the new lines to be deleted when there is no dot before "[".
But my sed command does not take into account my [^\.].
Without [^\.], I get :
blabla[3] foofoo
barbar.[4] blabla

You may use this sed (should work with non-gnu sed also):
sed -E -e ':a' -e 'N;$!ba' -e 's/((^|[^.])\[[0-9]+]) *\n\n/\1 /g' file
blabla[3] foofoo
barbar.[4]
blabla
Code Demo
Note that we are matching (^|[^.]) to allow [<digits>] to appear at the line start as well. It is also important to keep this part in capture group so that we don't miss out on this char in replacement.

Related

Replacing the test with sed

I'm trying to replace the text using the sed, but it's showing some error. Not getting where I'm getting wrong.
sed -i 's/process.env.REDIRECT_URI/http:\/\/test-domain.apps.io/\callback/g' input.txt
Have this :
process.env.REDIRECT_URI
Replace this with :
http://test-domain.apps.io
Try:
sed -i 's/process.env.REDIRECT_URI/http:\/\/test-domain.apps.io/g' input.txt
Notes:
The original command has a spurious string /\callback. All that was needed to make the code work was to remove it.
. is a wildcard. If you want to be sure that you are matching periods, they should be escaped:
sed -i 's/process\.env\.REDIRECT_URI/http:\/\/test-domain.apps.io/g' input.txt
Sometimes, its clearer if one doesn't have to escape /. One can use a separator of one's choice. For example, use #:
sed -i 's#process\.env\.REDIRECT_URI#http://test-domain.apps.io#g' input.txt
If you did want /callback in the output, use:
sed -i 's/process\.env\.REDIRECT_URI/http:\/\/test-domain.apps.io\/callback/g' input.txt
or:
sed -i 's#process\.env\.REDIRECT_URI#http://test-domain.apps.io/callback#g' input.txt

SED inplace file change inside make - How?

sed inplace change on a file is not working inside Make object.
I want to replace a line in a file with sed called in a make object. But it does not seem to be working. How can I fix this?
change_generics:
ifeq ($(run_TESTNAME), diagnostics)
ifeq ($(run_TESTCASE), 1)
sed -i -e "s/SIM_MULTI\==[a-z,A-Z]*/SIM_MULTI=TRUE/" ./generics.f
else ifeq ($(TESTCASE), 2)
sed -i -e "s/SIM_MISSED\==[a-z,A-Z]*/SIM_MISSED=TRUE/" ./generics.f
endif
endif
I would like the generics.f file changed with that one line change. But it remains the same as the original. The sed command works outside make.
I can't reproduce this using GNU sed 4.2.2 and GNU make 3.82, or at least, I can't reproduce any scenario where the same sed command works from the command line but not in a Makefile.
Simpler Makefile:
all:
# Contrived just so I can test your 2 sed commands.
sed -i -e "s/SIM_MULTI\==[a-z,A-Z]*/SIM_MULTI=TRUE/" ./generics.f
sed -i -e "s/SIM_MISSED\==[a-z,A-Z]*/SIM_MISSED=TRUE/" ./generics.f
Sample file content in generics.f:
SIM_MULTI=foo
SIM_MISSED=bar
Testing:
$ make all
sed -i -e "s/SIM_MULTI\==[a-z,A-Z]*/SIM_MULTI=TRUE/" ./generics.f
sed -i -e "s/SIM_MISSED\==[a-z,A-Z]*/SIM_MISSED=TRUE/" ./generics.f
Confirmed that both sed commands fail to edit a file with this content.
To fix:
Probably, you need to simply remove the \= from your regular expression. The backslash there has no effect, and causes your regex to simply match two equals signs ==. Thus this works:
all:
sed -i 's/SIM_MULTI=[a-zA-Z]*/SIM_MULTI=TRUE/' ./generics.f
sed -i 's/SIM_MISSED=[a-zA-Z]*/SIM_MISSED=TRUE/' ./generics.f
Testing:
$ make all
sed -i 's/SIM_MULTI=[a-zA-Z]*/SIM_MULTI=TRUE/' ./generics.f
sed -i 's/SIM_MISSED=[a-zA-Z]*/SIM_MISSED=TRUE/' ./generics.f
$ cat generics.f
SIM_MULTI=TRUE
SIM_MISSED=TRUE
Further explanation:
There is no need to specify -e there.
There is no need to enclose the script in double quotes, which is riskier because it allows the contents to be modified by the shell.
The bug appears to be \= and I deleted those characters, as mentioned above.
Note that I removed the comma , as well in [a-z,A-Z]. I think that probably isn't what you meant, and it would cause a class of characters including a-z, A-Z and a comma , to be matched by the regex. (And if it is what you mean, you might consider writing it as [a-zA-Z,] as that would be less confusing.)
If this has not resolved your issue, I would need to know things like:
What is the version of your sed.
What is the contents in generics.f.
POSIX/GNU sed have c for "change":
sed -i '/SIM_MULTI=/c\SIM_MULTI=TRUE'
sed -i '/SIM_MISSED=/c\SIM_MISSED=TRUE'

sed to copy part of line to end

I'm trying to copy part of a line to append to the end:
ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/900/169/985/GCA_900169985.1_IonXpress_024_genomic.fna.gz
becomes:
ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/900/169/985/GCA_900169985.1/GCA_900169985_IonXpress_024_genomic.fna.gz
I have tried:
sed 's/\(.*(GCA_\)\(.*\))/\1\2\2)'
$ f1=$'ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/900/169/985/GCA_900169985.1_IonXpress_024_genomic.fna.gz'
$ echo "$f1"
ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/900/169/985/GCA_900169985.1_IonXpress_024_genomic.fna.gz
$ sed -E 's/(.*)(GCA_.[^.]*)(.[^_]*)(.*)/\1\2\3\/\2\4/' <<<"$f1"
ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/900/169/985/GCA_900169985.1/GCA_900169985_IonXpress_024_genomic.fna.gz
sed -E (or -r in some systems) enables extended regex support in sed , so you don't need to escape the group parenthesis ( ).
The format (GCA_.[^.]*) equals to "get from GCA_ all chars up and excluding the first found dot" :
$ sed -E 's/(.*)(GCA_.[^.]*)(.[^_]*)(.*)/\2/' <<<"$f1"
GCA_900169985
Similarly (.[^_]*) means get all chars up to first found _ (excluding _ char). This is the regex way to perform a non greedy/lazy capture (in perl regex this would have been written something like as .*_?)
$ sed -E 's/(.*)(GCA_.[^.]*)(.[^_]*)(.*)/\3/' <<<"$f1"
.1
Short sed approach:
s="ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/900/169/985/GCA_900169985.1_IonXpress_024_genomic.fna.gz"
sed -E 's/(GCA_[^._]+)\.([^_]+)/\1.\2\/\1/' <<< "$s"
The output:
ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCA/900/169/985/GCA_900169985.1/GCA_900169985_IonXpress_024_genomic.fna.gz

sed to replace non-printable character with printable character

Am running BASH and UNIX utilities on Windows 7.
Have a file that contains a vertical tab. The binary symbol is 0x0B. The octal symbol is 013. I need to replace the symbol with a blank space.
Have tried this sed approach but it fails:
sed -e 's/'$(echo "octal-value")'/replace-word/g'
Specifically:
sed -e 's/'$(echo "\013")'/ /g'
Update:
Following this advice I use GNU sed and this approach:
sed -i 's:\0x0B: :g' file
but the stubborn vertical tab is still in the file.
What is the correct way to replace a non-printable character with a printable character?
Sed should recognise special characters:
sed -e 's/\x0b/ /g'
In answer to why the -e? If you use more than one sed expression, then each one must be preceded by the -e. So, for example:
echo foo bar bas zer | sed -e 's/zer/oh my/g' -e 's/bas/baz/'
would result in:
foo bar baz oh my
thus performing 2 different sed changes ('scripts) with only a single invocation. See sed man pages for more details.
(the above example is, obviously, contrived. I, however, have seen a sed command in a script with 78 individual -e 'scripts'!)
If you only have one 'script', then the -e is optional, obviously.

sed - substitute either of two characters with one command

I would like one sed command to accomplish the following:
$ sed s'/:/ /g' <and> sed s'/=/ /g'
That is, I would like to write
sed s'/<something>/ /g'
and have both = and : replaced by space.
sed s'/[:=]/ /g'
Brackets mean "any one of".
One option is also to use sed -e, like this. Although you don't need it in this case, it's however a good option to know about.
sed -e 's/:/ /' -e 's/..../ /' file
Sanjay's answer solves it. Another option that works with only one sed command is to separate each s substitution with a semicolon
sed 's/:/ /g ; s/=/ /g' file
or in separate lines in a script
sed 's/:/ /g
s/=/ /g' file
Those may be handy in other situations.