How to remove single quotes from a string using sed - bash

If I need to remove the following line from certain files
ob_start('ffggg_ggg');
I have tried
grep -rl "ob_start('ffggg_ggg');" /pathtosearch | xargs sed -i 's/[ob_start('ffggg_ggg');]//g'
but the rest of the characters have been removed except for single quotes.
How can I remove single quotes from a string using sed command?

Related

gsed replace by a variable $i with single quote

I have into a text file the following line :
\[Omega]BD=100;
I would like to replace with gsed the value 100 by a shell variable (zsh shell), here 600 :
I tried :
$ i=600
$ gsed 's/\[Omega]BD=.*/\[Omega]BD=\'\\"$i"\\';/' text_to_modify.txt | grep 600
but it returns me :
\[Omega]BD=\600; and not \[Omega]BD=600;
The is an additional backslash that I don't want, I wonder how could I remove this backslash. I would like to keep the two single quotes of gsed 's/.../.../'
Using sed;
i=600
$ sed "/\[Omega]/s/[[:digit:]]\+/$i/" input_file
\[Omega]BD=600;
You may use this sed command:
i=600
sed -E "s/(\\\\\[Omega]BD=).*/\1$i;/" file
\[Omega]BD=600;
We require additional escaping i.e. \\\\ to match a single \ because we are using double quotes around full sed command.
Or we can avoid you can use this combination of single and double quotes to avoid extra escaping:
sed -E 's/(\\\[Omega]BD=).*/\1'"$i;/" file

Escape "./" when using sed

I wanted to use grep to exclude words from $lastblock by using a pipeline, but I found that grep works only for files, not for stdout output.
So, here is what I'm using:
lastblock="./2.json"
echo $lastblock | sed '1,/firstmatch/d;/.json/,$d'
I want to exclude ./ and .json, keeping only what is between.
This sed command is correct for this purpose, but how to escape the ./ replacing firstmatch so it can work?
Thanks in advance!
Use bash's Parameter Substitution
lastblock="./2.json"
name="${lastblock##*/}" # strips from the beginning until last / -> 2.json
base="${name%.*}" # strips from the last . to the end -> 2
but I found that grep works only for files, not for stdout output.
here it is. (if your grep supports the -P flag.
lastblock="./2.json"
echo "$lastblock" | grep -Po '(?<=\./).*(?=\.)'
but how to escape the ./
With sed(1), escape it using a back slash \
lastblock="./2.json"
echo "$lastblock" | sed 's/^\.\///;s/\..*$//'
Or use a different delimiter like a pipe |
sed 's|^\./||;s|\..*$||'
with awk
lastblock="./2.json"
echo "$lastblock" | awk -F'[./]+' '{print $2}'
Starting from bashv3, regular expression pattern matching is supported using the =~ operator inside the [[ ... ]] keyword.
lastblock="./2.json"
regex='^\./([[:digit:]]+)\.json'
[[ $lastblock =~ $regex ]] && echo "${BASH_REMATCH[1]}"
Although a P.E. should suffice just for this purpose.
I wanted to use grep to exclude words from $lastblock by using a pipeline, but I found that grep works only for files, not for stdout output.
Nonsense. grep works the same for the same input, regardless of whether it is from a file or from the standard input.
So, here is what I'm using:
lastblock="./2.json"
echo $lastblock | sed '1,/firstmatch/d;/.json/,$d'
I want to exclude ./ and .json, keeping only what is between. This sed
command is correct for this purpose,
That sed command is nowhere near correct for the stated purpose. It has this effect:
delete every line from the very first one up to and including the next subsequent one that matches the regular expression /firstmatch/, AND
delete every line from the first one matching the regular expression /.json/ to the last one of the file (and note that . is a regex metacharacter).
To remove part of a line instead of deleting a whole line, use an s/// command instead of a d command. As for escaping, you can escape a character to sed by preceding it with a backslash (\), which itself must be quoted or escaped to protect it from interpretation by the shell. Additionally, most regex metacharacters lose their special significance when they appear inside a character class, which I find to be a more legible way to include them in a pattern as literals. For example:
lastblock="./2.json"
echo "$lastblock" | sed 's/^[.]\///; s/[.]json$//'
That says to remove the literal characters ./ appearing at the beginning of the (any) line, and, separately, to remove the literal characters .json appearing at the end of the line.
Alternatively, if you want to modify only those lines that both start with ./ and end with .json then you can use a single s command with a capturing group and a backreference:
lastblock="./2.json"
echo "$lastblock" | sed 's/^[.]\/\(.*\)[.]json$/\1/'
That says that on lines that start with ./ and end with .json, capture everything between those two and replace the whole line with the captured part alone.
You can use another character like '#' when you want to avoid slashes.
You can remember a part that matches and use it in the replacement.
Use [.] avoiding the dot to be any character.
echo "$lastblock" | sed -r 's#[.]/(.*)[.]json#\1#'
Solution!
Just discovered today the tr command thanks to this legendary, unrelated answer.
When searching all over Google for how to exclude "." and "/", 100% of StackOverflow answers didn't helped.
So, to escape characters from the output of a command, just append this pipe:
| tr -d "{character-emoji-anything-you-want-to-exclude}"
So, a full working and simple sample:
echo "./2.json" | tr -d "/" | tr -d "." | tr -d "json"
And done!

Mac OS Bash Sed yaml file with php file as string, backslash \n result only in n [duplicate]

Tool: Git Bash for Windows
Problem: Trying to insert the text "\connect central" at the top of each file in a directory.
Code:
for f in $DIR/*.sql; do
sed -i "1i \\\connect central" $f
done
This does try to edit inline and insert my text, but three backslashes (like I've read everywhere) doesn't create the single backslash like I'm expected. Instead I get:
I've also tried some variants along the lines of:
for f in $DIR/*.sql; do
sed -i -e "1i `\\\connect central`" $f
done
but that throws an error of sed: -e expression #1, char 3: expected \ aftera', c',i'`
Use single quotes instead of double quotes. Backslash is an escape character inside double quotes, so you need to double it to pass it through to the sed command literally. It has no special meaning inside single quotes.
sed -i '1i \\\connect central' "$f"
To do it with double quotes (which you might need if there's variable content in the string you're inserting), you have to double all the backslashes:
sed -i "1i \\\\\\connect central" "$f"
For more information, see Difference between single and double quotes in Bash

How to grep for filename with literal backslash and apostrophe

I have a script which in which I am trying to grep a log file for lines containing filenames with apostrophes that have been escaped with a backslash.
My grep code is:
grep -i saved logfile | grep "/path/to/file/filename contains spaces, apostrophe\'s, and commas"
The apostrophes in the logfile all have a preceding backslash so the following grep command works:
grep -i saved logfile | grep "/path/to/file/filename contains spaces, apostrophe\\\'s, and commas"
However I am trying to run this in a if statement where the filename is a variable:
if [[ ! $(grep -i saved logfile | grep "$i") ]]
which doesn't return a match.
How can I escape the backslash and the apostrophe to get a match with grep?
There are multiple layers here. The backslash has a special meaning both to grep and in the shell inside double-quoted strings. Things are simpler if you put the regex in single quotes, but then, of course, the regex cannot contain a single quote. But you can have a single quote in double quotes adjacent to the single-quoted string.
grep -i saved logfile |
grep '/path/to/file/filename contains spaces, apostrophe\\'"'"'s, and commas'
The first single-quoted string ends with apostrophe\\' and is followed by "'" -- a double-quoted string containing a single quote. That in turn is followed by another single-quoted string.
Alternatively, add enough backslashes to satisfy both the shell and grep.
grep -i saved logfile |
grep "/path/to/file/filename contains spaces, apostrophe\\\'s, and commas"
Of course, another alternative is to use grep -F which will match the entire string as a literal, i.e. dots will only match dots, not any character, asterisks will only match asterisks, not repetitions of the previous character, etc.
(The correct plural of "apostrophe" is simply "apostrophes", though.)
grep'ing for "\\'" works for me:
root#ultra:~# a="\\\'"
root#ultra:~# echo -e marley\\\'s\ ghost\\nmarley\'s ghost
marley\'s ghost
marley's ghost
root#ultra:~# echo -e marley\\\'s\ ghost\\nmarley\'s ghost | grep $a
marley\'s ghost
root#ultra:~#

Replacing "#", "$", "%", "&", and "_" with "\#", "\$", "\%", "\&", and "\_"

I have a plain text document, which I want to compile inside LaTeX. However, sometimes it has the characters, "#", "$", "%", "&", and "_". To compile properly in LaTeX, I must first replace these characters with "#", "\$", "\%", "\&", and "_". I have used this line in sed:
sed -i 's/\#/\\\#/g' ./file.txt
sed -i 's/\$/\\\$/g' ./file.txt
sed -i 's/\%/\\\%/g' ./file.txt
sed -i 's/\&/\\\&/g' ./file.txt
sed -i 's/\_/\\\_/g' ./file.txt
Is this correct?
Unfortunately, the file is too large to open in any GUI software, so checking if my sed line is correct with a text editor is difficult. I tried searching with grep, but the search does not work as expected (e.g. below, I searched for any lines containing "$"):
grep "\$" file.txt
What is the best way to put "\" in front of these characters?
How can I use grep to successfully check the lines with the replacements?
You can do the replacement with a single call to sed:
sed -i -E 's/([#$%&_\])/\\&/g' file.txt
The & in the replacement text fills in for whichever single character is enclosed in parentheses. Note that since \ is the LaTeX escape character, you'll have to escape it as well in the original file.
sed -i 's/\#/\\\#/g' ./file.txt
sed -i 's/\$/\\\$/g' ./file.txt
sed -i 's/\%/\\\%/g' ./file.txt
sed -i 's/\&/\\\&/g' ./file.txt
sed -i 's/\_/\\\_/g' ./file.txt
You don't need the \ on the first (search) string on most of them, just $ (it's a special character, meaning the end of a line; the rest aren't special). And in the replacement, you only need two \\, not three. Also, you could do it all in one with several -e statements:
sed -i.bak -e 's/#/\\#/g' \
-e 's/\$/\\$/g' \
-e 's/%/\\%/g' \
-e 's/&/\\&/g' \
-e 's/_/\\_/g' file.txt
You don't need to double-escape anything (except the \\) because these are single-quoted. In your grep, bash is interpreting the escape on the $ because it's a special character (specifically, a sigil for variables), so grep is getting and searching for just the $, which is a special character meaning the end of a line. You need to either single-quote it to prevent bash from interpreting the \ ('\$', or add another pair of \\: "\\\$". Presumably, that's where you're getting the\` from, but you don't need it in the sed as it's written.
I think your problem is that bash itself is handling those escapes.
What you have looks right to me. But warning: it will also doubly escape e.g. a \# that is already escaped. If that's not what you want, you might want to modify your patterns to check that there isn't a preceding \ already.
$ is used for bash command substitution syntax. I guess grep "\\$" file.txt should do what you expect.
I do not respond for sed, the other answers are good enougth ;-)
You can use less as viewer to check your huge file (or more, but less is more comfortable than more).
For searching, you can use fgrep: it ignores regular expression => fgrep '\$' will really search for text \$. fgrep is the same as invoking grep -F.
EDIT:
fgrep '\$' and fgrep "\$" are different. In the second case, bash interprets the string and will replace it by a single character: $ (i.e. fgrep will search for $ only).

Resources