Error using sed command to replace references to include file that has changed name - sed

I've renamed an include file and I'd like to replace all references to it in my code, all files are in the same directory.
After researching several websites, I keep getting errors when I try the following (however it seems to work for others, maybe because I'm using Mac OS X)
grep -rl 'old-file.php' . | xargs sed -i 's/old-file.php/new-file.php/g'
I seem to get an error relating to the first grep matched file:
sed: 1: "./somefile.php": invalid command code .
I've tried various forms of escaping the . ([.] and .) neither seem to work.
Any helpful suggestions are most welcome!

grep -rl 'old-file.php' . | xargs sed -i 's#old-file.php#new-file.php#g'
use other separator than / in this sed (or escape the /)
now if the ./someFile is in the nsearch pattern (old-file) use maybe [.] or \. in this part of the sed. to avoid other matching value like (ba)d/old_file.php

Related

Remove space between a keyword and paranthesis

I have nearly 300 files in 60 folders .
As per the C++ coding guidelines, I need to replace below lines from *.cpp and *.cl files (wants to remove extra space between if and for statement) -
for (* .....)
with
for(* .....)
and also
if (* .....)
with
if(* .....)
Can any one suggest me the grep command to do search and replace for all files.
Edited:
I tried with below commands:
sed -i 's/for (/for(/g' *.cpp
But got error like below:
sed: can't read *.cpp: No such file or directory
I think you need sed command (stream editor, see man sed on your mashine). It is more suitable for file editing.
sed -i -E 's/(for|if)[ ]+(\(.*\))/\1\2/g'
Let me explain:
-i stands for inline, that means that all changes will be done and saved in the file
-E is needed to use extended regular expression inside with sed
s/(for|if)[ ]+(\(.*\))/\1\2/g
s stands for substitute
/ is a separator, which separates different parts of command. Between first / and second / there is pattern that you need to find (and then replace). After second / and third / there that we want to have after substitution.
g in the end stands for global, that means to make changes in the whole file.
How to apply to every file that you need?
This question is already exist, so in the end you need to run in directory where are your files stored following command
find ./ -type f -exec sed -i -E 's/(for|if)[ ]+(\(.*\))/\1\2/g' {} \;
I hope, this will help:)
I have created the file "brol.txt", with following content:
for (correct
for(wrong
if (correct
if(wrong
I have launched following grep command:
grep -E "for \(|if \(" brol.txt
With following result:
for (correct
if (correct
Explanation:
grep -E means extended grep (allows to search for expression1 OR expression2,
separated by a pipe character)
\( means the search for a round bracket. The backslash is an escape character.

"invalid command code ." error from sed after running find and sed on Mavericks

I run the following command to find and replace an old web address to a new one.
find . -type f -print0 | xargs -0 sed -i \
's/http:\/\/www\.oldwebaddress\.com\/techblog/https:\/\/github\.com\/myname/g'
However I get the following error.
sed: 1: "./.DS_Store": invalid command code .
I tried this one after reading some of Stack Overflow posts but didn't work either.
find . -type f -print0 | xargs -0 sed -i "" \
's/http:\/\/www\.oldwebaddress\.com\/techblog/https:\/\/github\.com\/myname/g'
sed: RE error: illegal byte sequence
What am I doing wrong here?
The sed on Mac OS X accepts the -i option but requires an argument, the suffix to use for the backup files. It is not optional as it is with GNU sed. So, the sed script tries to use your s/// command as the suffix, and then the first file name didn't happen to be a valid sed command.
For the second attempt, with -i "", it is not quite so clear what's up. I assume there's either a backslash after the "" or the whole lot is really on one line, so that it is syntactically correct.
It is simpler to use some character other than / as the separator when editing path names. Often, % works:
-e 's%http://www\.oldwebaddress\.com/techblog%https://github\.com/myname%g'
but you can use any character; Control-A or Control-G are quite effective too and even more unlikely to appear in a URL than %.
It is not clear to me, though, why you're getting the RE error (invalid byte sequence). Copying and pasting from the question doesn't show a problem, and the other question referenced suggests LANG=C LC_CTYPE=C but I'm not running into problems with LANG=en_US.UTF-8 and nothing set for LC_CTYPE.
Does this help?
Also if you will just do -print instead of -print0 then you can replace xargs -0 with just xargs.
You might also consider using perl instead of BSD sed.
find . -type f -print | xargs perl -pi.bak -e 's/http\:\/\/www\.oldwebaddress\.com\/techblog/https\:\/\/github\.com\/myname/g'
Above should do the replacements and save all files backups adding .bak at the end of filenames. Use perl -pi -e if you don't want backups to be created.

Using sed on a string that contains reg expressions

I'm trying to do a find/replace and an insert with sed but I keep getting a message that says "extra characters at the end of n command." I'm also not running this from the terminal, it's embedded in a shell script so I can send it to others.
This is what I'm trying to run
sed -i 's/include "/var/run/racoon/*.conf" ;/# include "/var/run/racoon/*.conf" ;/g' ~/Documents/test.conf;
sed '$a; include "/etc/racoon/remote/*.conf" ;/g' ~/Documents/test.conf;
To make it easier to see, I'm trying to replace
include "/var/run/racoon/*.conf" ;
with
# include "/var/run/racoon/*.conf" ;
and then add this
include "/etc/racoon/remote/*.conf" ;
Basically, I just want to comment out the last line of a file and then insert a line after it. I'm pretty new to sed so I'm not sure if I'm going about this all wrong, any help will be appreciated!
There are at least 2 problems with what you're trying:
You need to use different delimiters since your pattern and replacement contain /. You can use |.
The * in the pattern needs to be escaped, \*.
As such, the first expression would look like:
sed -i 's|include "/var/run/racoon/\*.conf" ;|# include "/var/run/racoon/*.conf" ;|g' ~/Documents/test.conf;
Similarly, change the second one.
In case anybody runs into this problem, you either have to download gnu-sed or do it by other means.
You can download gnu-sed easily if you have Homebrew installed.
brew install gnu-sed
Or you can use perl and printf like I did
To do the replacement
sudo perl -pi -e 's|include "/var/run/racoon/\*.conf" ;|# include "/var/run/racoon/*.conf" ;|g' /etc/racoon/racoon.conf;
To add a line. It will always be line 139 for me so I could go this route.
line='include "/etc/racoon/remote/*.conf" ;'
sudo printf '%s\n' H 139i "$line" . wq | ed -s /etc/racoon/racoon.conf
Thank you to devnull for helping me get my syntax right.

What is the purpose of the "-" in sh script line: ext="$(echo $ext | sed 's/\./\\./' -)"

I am porting a sh script that was apparently written using GNU implementation of sed to BSD implementation of sed. The exact line in the script with the original comment are:
# escape dot in file extension to grep it
ext="$(echo $ext | sed 's/\./\\./' -)"
I am able to reproduce a results with the following (obviously I am not exhausting all possibilities values for ext) :
ext=.h; ext="$(echo $ext | sed 's/\./\\./' -)"; echo [$ext]
Using GNU's implementation of sed the following is returned:
[\.h]
Using BSD's implementation of sed the following is returned:
sed: -: No such file or directory
[]
Executing ext=.h; ext="$(echo $ext | sed 's/\./\\./')"; echo [$ext] returns [\.h] for both implementation of sed.
I have looked at both GNU and BSD's sed's man page have not found anything about the trailing "-". Googling for sed with a "-" is not very fruitful either.
Is the "-" a typo?
Is the "-" needed for some an unexpected value of $ext?
Is the issue not with sed, but rather with sh?
Can someone direct me to what I should be looking at, or even better, explain what the purpose of the "-" is?
On my system, that syntax isn't documented in the man page, but it is in the
'info' page:
sed OPTIONS... [SCRIPT] [INPUTFILE...]
If you do not specify INPUTFILE, or if INPUTFILE is -',sed'
filters the contents of the standard input.
Given that particular usage, I think you could leave off the '-' and it should
still work.
You got your specific question answered BUT your script is all wrong. Take a look at this:
# escape dot in file extension to grep it
ext="$(echo $ext | sed 's/\./\\./')"
The main problems with that are:
You're not quoting your variable ($ext) so it will go through file name expansion plus if it contains spaces will be passed to echo as multiple arguments instead of 1. Do this instead:
ext="$(echo "$ext" | sed 's/\./\\./')"
You're using an external command (sed) and a pipe to do something the shell can do trivially itself. Do this instead:
ext="${ext/./\.}"
Worst of all: You're escaping the RE meta-character (.) in your variable so you can pass it to grep to do an RE search on it as if it were a string - that doesn't make any sense and becomes intractable in the general case where your variable could contain any combination of RE metacharacters. Just do a string search instead of an RE search and you don't need to escape anything. Don't do either of the above substitution commands and then do either of these instead of grep "$ext" file:
grep -F "$ext" file
fgrep "$ext" file
awk -v ext="$ext" 'index($0,ext)' file

Unable to filter rows which contain "Is a directory" by SED/AWK

I run the code gives me the following sample data
md5deep find * | awk '{ print $1 }'
A sample of the output
/Users/math/Documents/Articles/Number theory: Is a directory
258fe6853b1bfb2d07f512ff6bec52b1
/Users/math/Documents/Articles/Probability and statistics: Is a directory
4811bfb2ad04b9f4318049c01ebb52ef
8aae4ac3694658cf90005dbdea37b4d5
258fe6853b1bfb2d07f512ff6bec52b1
I have tried to filter the rows which contain Is a directory by SED unsuccessfully
md5deep find * | awk '{ print $1 }' | sed s/\/*//g
Its sample output is
/Users/math/Documents/Articles/Number theory: Is a directory
/Users/math/Documents/Articles/Topology: Is a directory
/Users/math/Documents/Articles/useful: Is a directory
How can I filter Out each row which contains "Is a directory" by SED/AWK?
[clarification]
I want to filter out the rows which contain Is a directory.
I have not used the md5deep tool, but I believe those lines are error messages; they would be going to standard error instead of standard out, and so they are going directly to your terminal instead of through the pipe. Thus, they won't be filtered by your sed command. You could filter them by merging your standard error and standard output streams, but
It looks like (I'm not sure because you are missing the backquotes) you are trying to call
md5deep `find *`
and find is returning all of the files and directories.
Some notes on what you might want to do:
It looks like md5deep has a -r for "recursive" option. So, you may want to try:
md5deep -r *
instead of the find command.
If you do wish to use a find command, you can limit it to only files using -type f, instead of files and directories. Also, you don't need to pass * into a find command (which may confuse find if there are files that have names that looks like the options that find understands); passing in . will search recursively through the current directory.
find . -type f
In sed if you wish to use slashes in your pattern, it can be a pain to quote them correctly with \. You can instead choose a different character to delimit your regular expression; sed will use the first character after the s command as a delimiter. Your pattern is also lacking a .; in regular expressions, to indicate one instance of any character you use ., and to indicate "zero or more of the preceding expression" you use *, so .* indicates "zero or more of any character" (this is different from glob patterns, in which * alone means "zero or more of any character").
sed "s|/.*||g"
If you really do want to be including your standard error stream in your standard output, so it will pass through the pipe, then you can run:
md5deep `find *` 2>&1 | awk ...
If you just want to ignore stderr, you can redirect that to /dev/null, which is a special file that just discards anything that goes into it:
md5deep `find *` 2>/dev/null | awk ...
In summary, I think the command below will help you with your immediate problem, and the other suggestions listed above may help you if I did not undersand what you were looking for:
md5deep -r * | awk '{ print $1 }'
To specifically answer the clarification: how to filter out lines using awk and sed:
awk '/Is a directory/ {next} {print}'
sed 'g/Is a directory/d'
Why not use grep instead?
ie,
md5deep find * | grep "Is a directory" | awk '{ print $1 }'
Edit: I just re-read your question and if you want to remove the lines with Is a directory, use the -v flag of grep, ie:
md5deep find * | grep -v "Is a directory" | awk '{ print $1 }'
I'm not intimately familiar with md5deep, but this may do something like you are tying to do.
find -type f -exec md5sum {} +