Batch File using sed in windows - unexpected append instead of replace - batch-file

I've been tasked with migrating a group of batch scripts to Windows 7 (from XP) and have had a few problems using sed for substitution. What i need the line to do is find LogPath and anything inside the double quotes should be replaced with ABC (just for testing - will actually be a UNC path).
However instead I'm getting two strange problems:
it's deleting the first double quote
more importantly it isn't
actually replacing anything inside the quotes, but instead is just
appending to this string
Here is the relevant line of the script:
sed \\fs-bri-01\9732\9732.hfls -i -e s,LogPath="*.",LogPath="ABC",g
This script works on Windows XP but not Windows 7.

Maybe the problem comes from the UNC path:
pushd \\fs-bri-01\9732
sed 9732.fls -i -e s,LogPath="*.",LogPath="ABC",g
popd
But maybe the problem comes from the quote characters and the way sed gets its argv array. Then you can try:
sed -i -e "s/LogPath=\".*\"/LogPath=\"ABC\"/g" \\fs-bri-01\9732\9732.hfls

Well figured a work around posting it below for anyone stuck in the same situation.
sed \\fs-bri-01\9732\9732.hfls -i -e "s/LogPath=\"[\:A-Z0-9a-z_\\\/\.\ ]*\"/LogPath=\"ABC\"/g"

Related

sed: how to replace sth. by a backslash followed by reference

Despite all the sed-backslash discussions on Stackoverflow I cannot find a working solution for my specific problem. I want to precede a certain string in a file by a backslash: something -> \something.
sed -i -- 's/\(something\)/\\\1/g' file
This always returns the string \1 instead of \something, because for some reason sed thinks it should escape the third backslash. The (from my point of view more logical) behaviour can be achieved by inserting a space between \\ and \1 in the sed command, but then the result is \ something (i.e. with an inserted space in the result) which is not what I want.
I am running this command in a batch file on Windows, using sed from cygwin (I hope this does not matter as I am aiming for a cross-platform solution).
EDIT: /usr/bin/sed version 4.2.2.
In Windows cmd with Cygwin, use this sed command:
sed -e 's/\(something\)/\\\\\1/g' file
You can start your script from a batch file
myBatch.bat
#echo off
c:\cygwin64\bin\bash ./mySed
mySed
#!/bin/bash
echo asdfsomethingasdf | sed 's/\(something\)/\\\1/g'
It can be necessary to use /usr/bin/sed when your path isn't completely set

sed addressing for each of multiple input files

I would like to print from line 10 until the end of the file for each of several files in a folder. For a single file, I would do this with sed -n '10,$p', however when providing multiple input files to sed the addressing becomes in terms of the concatenated files. How can I print using the sed command and address each file's line numbers? This website says that the $ addressing character refers to each file's end if the -s option is used, but this does not work for me on my Macbook Pro.
Ideally I would like the whole procedure to be done with a single tool without writing a loop. I'm ok with the output being concatenated. I'm open to other tools than sed. tail might work for this like so tail -n +10 filenames but this is very very slow, so I imagine sed is better to use.
awk 'FNR>9{print $0}' file1 file2
This will do it

sed command works fine under shell terminal, but fails in 'system()' call under C code

I'm trying to delete some special lines in a log file, so I use sed of busybox on an embeded linux system.
# sed
BusyBox v1.18.4 (2013-01-16 16:00:18 CST) multi-call binary.
Usage: sed [-efinr] SED_CMD [FILE]...
Options:
-e CMD Add CMD to sed commands to be executed
-f FILE Add FILE contents to sed commands to be executed
-i Edit files in-place (else sends result to stdout)
-n Suppress automatic printing of pattern space
-r Use extended regex syntax
If no -e or -f, the first non-option argument is the sed command string.
Remaining arguments are input files (stdin if none).
execute the following command under shell and everything works fine:
export MODULE=sshd
sed "/$MODULE\[/d" logfile
but if I try to use the following C code to accomplish this:
char logfile[] = "logfile";
char module_str[] = "sshd";
char env_str[64] = {0};
int offset = 0;
strcpy(env_str, "MODULE=");
offset += strlen("MODULE=");
strcpy(env_str + offset, module_str);
putenv(env_str);
system("sed \"/$MODULE\[/d\" logfile");
when executing the a.out, I got the error message:
sed: unmatched '/'
what's wrong with my 'system()' call? I'm totally a newbie in text processing, so anybody can give me some clue? Thanks.
Best regards,
dejunl
straight off I can see that the \ before the [ is going to be swallowed by 'C'
so you'll need to double it,
system("sed \"/$MODULE\\[/d\" logfile");
But the shell might want to swallow the one that's left swallow that one so double it again
system("sed \"/$MODULE\\\\[/d\" logfile");
of course system("sed \"/$MODULE\\[/d\" logfile"); can't be sure I'm reading the question you posed. try it with echo instead of sed and adjust it until the string comes out as you want sed to see it.

How do I let sed 'w' command know where the filename ends?

Every example I was able to find demonstrating the w command of sed has it in the end of the script. What if I can't do that?
An example will probably demonstrate the problem better:
$ echo '123' | sed 'w tempfile; s/[0-9]/\./g'
sed: couldn't open file tempfile; s/[0-9]/\./g: No such file or directory
(How) can I change the above so that sed knows where the filename ends?
P.S. I'm aware that I can do
$ echo '123' | sed 'w tempfile
> s/[0-9]/\./g'
...
Are there prettier options?
P.P.S. People tend to suggest to split it in two scripts. The question is then: is it safe? What if I was going to branch somewhere after the w command, and so on. Can someone confirm that any script can be split in two after any command and that will not affect the results?
Final edit: I checked that multiple -e work just as concatenated commands. I thought it was more complex (like the first one should always exit before the second one starts, etc.). However, I tried splitting a {..} block of commands between two scripts and it still worked, so the w thing is really not a serious problem. Thanks to all.
You can give a two line script to sed in one shell line:
echo '123' | sed -e 'w tempfile' -e 's/[0-9]/\./g'
This might work for you (if you're using BASH and probably GNU sed):
echo '123' | sed 'w tempfile'$'\n'';s/[0-9]/\./g'
Explanation:
The r, R and w commands need a newline to terminate the file name.
The answer to the question is "newline":
sed will treat a non-escaped literal newline as the end of the file name.
If your shell is bash, or supports the $'\n' syntax, you can solve the OP's original question this way:
echo '123' | sed 'w tempfile'$'\n''s/[0-9]/\./g'
In a more limited sh you can say
$ echo '123' | sed 'w tempfile'\
> 's/[0-9]/\./g'
What I did here was write \ as an escape, then hit enter and wrote the rest of the command there. Note that here I am escaping the newline from bash but it is being passed to sed.
Reverse the 2 sed command sequences like this:
echo '123' | sed 's/[0-9]/\./g;w tempfile'
i.e. perform replacements first and then write pattern space into a file.
EDIT: There was some misunderstanding whether OP wants replaced text in final file or not. My above command puts replaced text in tempfile. Since this is not what OP wanted here is one more version that avoids it:
echo '123' | sed -e 'h;s/[0-9]/\./g;g;w tempfile'

Batch file to edit multiple .txt files

I have over 1300 .txt files where I need to edit the first line of text, replacing one name for another. Can someone please advise of the best way to achieve this?
Any advice would be appreciated.
Thanks
Stu
If this is Linux, then sed is the answer.
Use sed. Here's a simple one-liner that would do what you want:
sed -i '1s/oldtext/newtext/' *.txt
The -i tells sed to edit the files in-place. The 1 at the beginning of the pattern applies it only to the first line. The s// constrution replaces the text.
perl -npi~ -e "s/old/new/g" file.txt
If you're on a Windows machine, install Strawberry Perl.

Resources