How can I avoid creation of the extra file with `-e` while using the sed tool in a shell script? - bash

I am using sed command in a shell script to edit & replace some file content of an xml file in a osx(unix) environment. Is there some way I can avoid sed creating the temporary files with -e ? I am doing the following in my script to edit a file with sed.
sed -i -e 's/abc/xyz/g' /PathTo/MyEditableFile.xml
Above sed command works great but creates an extra file as /PathTo/MyEditableFile.xml-e
How can I avoid creation of the the extra file with -e there ?
I tried some options like setting a temporary folder path to sed so that it creates the temporary file in /tmp/. Like so:
sed -i -e 's/abc/xyz/g' /PathTo/MyEditableFile.xml >/tmp
But doesnt seem to work

As you are editing the file in place (-i), OS X sed requires a mandatory backup filename.
You can use -i "" to get around this:
sed -i "" -e 's/abc/xyz/g' /PathTo/MyEditableFile.xml

Related

Bash script using sed to append line at end of file if line doesn't exist on mac

I need to use sed instead of echo and append to the end of a file: list.txt
list.txt has a list of directories:
/desktop/test1/file1
/desktop/test2/file1
I need to append another directory with slashes to this list.txt at the end of the file if that directory already doesn't exist in the list. Such as: /desktop/file1
The result should be:
/desktop/test1/file1
/desktop/test2/file1
/desktop/file1
I've tried using this script but am running into syntax errors with the a command which I've been seeing could be a mac issue?:
#!/bin/bash
if ! grep -q "/desktop/file1" user/admin/Desktop/list.txt; then
sed -i -e '$a/desktop/file1' user/admin/Desktop/list.txt
fi
The a command is used as a\ in standard sed and should be followed by a newline and the text to be written. The form you use is a GNU extension. So a standard sed command to do the job could be:
sed -i '' '$a\
/desktop/file1' user/admin/Desktop/list.txt
or
sed -i '' '$a\'$'\n''/desktop/file1' user/admin/Desktop/list.txt
using ANSI-C quoting in bash.

Replacing a value in a file using Shell Scripting

I want to replace a string in linux file with a variable value using Shell Script:
Tried doing this in shell script, but not working.
sed -i "s/$StrVal1/$StrVal2/" "$TargetFile"
Please help.
I think you forgot the "g" in the sed command. Works for me on my linux shell. You can also cat the file and then run the sed command.
First I define variables as shown below, on the prompt:
a='class'; b='CLASS'
Then I cat the file with a sed command:
cat a.txt | sed "s/$a/$b/g"
So my input file is like
class="pending">Count
class="completed">Count
My output with that command is like
CLASS="pending">Count:
CLASS="completed">Count:

How to change string in file, but saving the changes in another file, not orginal one?

I have a small problem. In my original.txt file I got some scheme with one variable zmuser to change.
I'm using sed command to change my variable 'zmuser' to other string, which is also a variable.
sed -i -e s/zmuser/${user}/g original.txt
It changes the zmuser for my $user variable in original.txt.
How can I make changes from the file original.txt but save it in another .txt file?
This should do it:
sed -e "s/zmuser/${user}/g" original.txt > another.txt
How it works:
If you omit the -i flag from your sed command, the output will be printed on stdout. The > another.txt construct redirects that output to another.txt file.
you can also do
sed -n -e "s/zmuser/${user}/g" -e "w another.txt" original.txt

replace a string in file using shell script

Suppose my file a.conf is as following
Include /1
Include /2
Include /3
I want to replace "Include /2" with a new line, I write the code in .sh file :
line="Include /2"
rep=""
sed -e "s/${line}/${rep}/g" /root/new_scripts/a.conf
But after running the sh file, It give me the following error
sed: -e expression #1, char 14: unknown option to `s'
If you are using a newer version of sed you can use -i to read from and write to the same file. Using -i you can specify a file extension so a backup will be made, incase something went wrong. Also you don't need to use the -e flag unless you are using multiple commands
sed -i.bak "s/${line}/${rep}/g" /root/new_scripts/a.conf
I have just noticed that as the variables you are using are quoted strings you may want to use single quotes around your sed expression. Also your string contains a forward slash, to avoid any errors you can use a different delimiter in your sed command (the delimiter doesn't need to be a slash):
sed -i.bak 's|${line}|${rep}|g' /root/new_scripts/a.conf
You have to write the changes to a new file and then, move the new file over the old one. Like this:
line="Include 2"
rep=""
sed -e "s/${line}/${rep}/g" /root/new_scripts/a.conf > /root/new_scripts/a.conf-new
mv /root/new_scripts/a.conf-new /root/new_scripts/a.conf
The redirection (> /root/new_scripts/a.conf) wipes the contents of the file before sed can see it.
You need to pass the -i option to sed to edit the file in-place:
sed -i "s/${line}/${rep}/g" /root/new_scripts/a.conf
You can also ask sed to create a backup of the original file:
sed -i.bak "s/${line}/${rep}/g" /root/new_scripts/a.conf
So, if you have to replace a substring in a file, you can use sed command like this, say we have a file as file.txt, so replacing a substring in it can be done like this
searchString="abc";
replaceString="def";
sed -i '' "s|$searchString|$replaceString|g" file.txt
This will all the occurrences of "abc" with "def" in file.txt. Also, this keeps a check for any / character present in the variables used, and with no backup file made.

sed command creates randomly named files

I recently wrote a script that does a sed command, to replace all the occurrences of "string1" with "string2" in a file named "test.txt".
It looks like this:
sed -i 's/string1/string2/g' test.txt
The catch is, "string1" does not necessarily exist in test.txt.
I notice after executing a bunch of these sed commands, I get a number of empty files, left behind in the directory, with names that look like this:
"sed4l4DpD"
Does anyone know why this might be, and how I can correct it?
-i is the suffix given to the new/output file. Also, you need -e for the command.
Here's how you use it:
sed -i '2' -e 's/string1/string2/g' test.txt
This will create a file called test.txt2 that is the backup of test.txt
To replace the file (instead of creating a new copy - called an "in-place" substitution), change the -i value to '' (ie blank):
sed -i '' -e 's/string1/string2/g' test.txt
EDIT II
Here's actual command line output from a Mac (Snow Leopard) that show that my modified answer (removed space from between the -i and the suffix) is correct.
NOTE: On a linux server, there must be no space between it -i and the suffix.
> echo "this is a test" > test.txt
> cat test.txt
this is a test
> sed -i '2' -e 's/a/a good/' test.txt
> ls test*
test.txt test.txt2
> cat test.txt
this is a good test
> cat test.txt2
this is a test
> sed -i '' -e 's/a/a really/' test.txt
> ls test*
test.txt test.txt2
> cat test.txt
this is a really good test
I wasn't able to reproduce this with a quick test (using GNU sed 4.2.1) -- but strace did show sed creating a file called sedJd9Cuy and then renaming it to tmp (the file named on the command line).
It looks like something is going wrong after sed creates the temporary file and before it's able to rename it.
My best guess is that you've run out of room in the filesystem; you're able to create a new empty file, but unable to write to it.
What does df . say?
EDIT:
I still don't know what's causing the problem, but it shouldn't be too difficult to work around it.
Rather than
sed -i 's/string1/string2/g' test.txt
try something like this:
sed 's/string1/string2/g' test.txt > test.txt.$$ && mv -f test.txt.$$ test.txt
Something is going wrong with the way sed creates and then renames a text file to replace your original file. The above command uses sed as a simple input-output filter and creates and renames the temporary file separately.
So after much testing last night, it turns out that sed was creating these files when trying to operate on an empty string. The way i was getting the array of "$string1" arguments was through a grep command, which seems to be malformed. What I wanted from the grep was all lines containing something of the type "Text here '.'".
For example the string, "Text here 'ABC.DEF'" in a file, should have been caught by grep, then the ABC.DEF portion of the string, would be substituted by ABC_DEF. Unfortunately the grep I was using would catch lines of the type "Text here ''" (that is, nothing between the ''). When later on, the script attempted to perform a sed replacement using this empty string, the random file was created (probably because sed died).
Thanks for all your help in understanding how sed works.
Its better if you do it in this way:
cat large_file | sed 's/string1/string2/g' > file_filtred

Resources