Egrep results are current command and grabage - linux

Im trying to egrep lines that contain nothing but a single occurrence of "Hihihihihihihi!", with arbitrarily many 'hi's
Here is what I write
egrep "^Hi(hi)*!$" myfile.txt
But it didn't work. After pressing enter, the command was displayed again:
egrep "^Hi(hi)*myfile.txt" mayflies.txt
Anyone can help me?
Thanks!

The shell is interpreting !$ to substitute the last argument of the previous commend.
To disable these shell substitutions, change the double quotes to single quotes.
egrep '^Hi(hi)*!$' myfile.txt
Alternatively, you can use the -x switch to match only whole lines, obviating the need for the ^ and $ characters, and thus avoiding the fatal !$ argument substitution:
egrep -x "Hi(hi)*!" myfile.txt

You don't say what shell, but I suspect the problem you have is that the exclamation mark (!) is extra special to the shell. You need to escape that:
egrep "^Hi(hi)*\!$" myfile.txt
Should work in most shells where that's true.
Changing the double quotes to single quotes is not enough for all shells, the exclamation is still special inside single quotes. I just tested all this in the tcsh, other shells will have differences.

try it with single quotes. I think the $ is being interpreted by BASH as something, not sure what:
egrep '^Hi(hi)*!$' myfile.txt

Related

Trying to understand meaning of non-shell matacharacters in linux

Can anyone help me understand the meaning of
grep "[0-9]\{2\}" filename
It is a non-shell matacharacter command.
grep needs the curly braces backslashed in quantifiers.
grep '[0-9]\{2\}' # n.b. the single quotes
In double quotes, \{ is expanded as {, you need to backslash the backslash to get it through.

How to use variables in linux regex pattern?

I need to execute a sed command with pattern /^03.06.2014/ in a .sh script & command line. The date is a variable not a constant. How could i implement this? When I use a variable inside a regex pattern, the command breaks. Do I need to escape something here? Any help is appreciated. Thanks!
date=$(date +%m.%d.%Y)
sed -n '/^$date/,$p' filename
Use double quotes for variable expansion in sed
sed -n "/^$date/,\$p" filename
You need to use double quotes to allow for shell expansion. You'll need to escape the $ meaning EOF.
sed -n "/^$date/,\$p" filename

Escape file name for use in sed substitution

How can I fix this:
abc="a/b/c"; echo porc | sed -r "s/^/$abc/"
sed: -e expression #1, char 7: unknown option to `s'
The substitution of variable $abc is done correctly, but the problem is that $abc contains slashes, which confuse sed. Can I somehow escape these slashes?
Note that sed(1) allows you to use different characters for your s/// delimiters:
$ abc="a/b/c"
$ echo porc | sed -r "s|^|$abc|"
a/b/cporc
$
Of course, if you go this route, you need to make sure that the delimiters you choose aren't used elsewhere in your input.
The GNU manual for sed states that "The / characters may be uniformly replaced by any other single character within any given s command."
Therefore, just use another character instead of /, for example ::
abc="a/b/c"; echo porc | sed -r "s:^:$abc:"
Do not use a character that can be found in your input. We can use : above, since we know that the input (a/b/c/) doesn't contain :.
Be careful of character-escaping.
If using "", Bash will interpret some characters specially, e.g. ` (used for inline execution), ! (used for accessing Bash history), $ (used for accessing variables).
If using '', Bash will take all characters literally, even $.
The two approaches can be combined, depending on whether you need escaping or not, e.g.:
abc="a/b/c"; echo porc | sed 's!^!'"$abc"'!'
You don't have to use / as pattern and replace separator, as others already told you. I'd go with : as it is rather rarely used in paths (it's a separator in PATH environment variable). Stick to one and use shell built-in string replace features to make it bullet-proof, e.g. ${abc//:/\\:} (which means replace all : occurrences with \: in ${abc}) in case of : being the separator.
$ abc="a/b/c"; echo porc | sed -r "s:^:${abc//:/\\:}:"
a/b/cporc
backslash:
abc='a\/b\/c'
space filling....
As for the escaping part of the question I had the same issue and resolved with a double sed that can possibly be optimized.
escaped_abc=$(echo $abc | sed "s/\//\\\AAA\//g" | sed "s/AAA//g")
The triple A is used because otherwise the forward slash following its escaping backslash is never placed in the output, no matter how many backslashes you put in front of it.

replace using sed

I want to replace IP dynamically but somehwo sed is placing word $IP instead of actual value.
IP=10.50.33.44
PORT=5774
sed -i~ 's/https:\/\/10.11.12.13:8443/https:\/\/$IP:$PORT/g' abc.txt
Can you help me out in getting the correct value?
Use double quotes" for variable expansion:
sed -i~ "s/https:\/\/10.11.12.13:8443/https:\/\/$IP:$PORT/g" abc.txt
and as #Joachim said, use different delimiter. For example,
sed -i~ "s;https://10.11.12.13:8443;https://$IP:$PORT;g" abc.txt
Variation on a theme: I always use single quotes to surround sed/awk/perl... commands as the shell can sometimes trip you up when using double quotes.
I find it best to double quote the variables:
sed -i~ 's/https:\/\/10.11.12.13:8443/https:\/\/'"$IP"':'"$PORT"'/g' abc.txt
As a "belt and braces" and as I usually compose my commands interactively at the command line in bash, the key-binding M-C-e (that's Alt-Control-e on most keyboards) will interpolate the command before it's sent. Letting you visually see what the command is really getting.

shell scripting for token replacement in all files in a folder

HI
I am not very good with linux shell scripting.I am trying following shell script to replace
revision number token $rev -<rev number> in all html files under specified directory
cd /home/myapp/test
set repUpRev = "`svnversion`"
echo $repUpRev
grep -lr -e '\$rev -'.$repUpRev.'\$' *.html | xargs sed -i 's/'\$rev -'.$repUpRev.'\$'/'\$rev -.*$'/g'
This seems not working, what is wrong with the above code ?
rev=$(svnversion)
sed -i.bak "s/$rev/some other string/g" *.html
What is $rev in the regexp string? Is it another variable? Or you're looking for a string '$rev'. If latter - I would suggest adding '\' before $ otherwise it's treated as a special regexp character...
This is how you show the last line:
grep -lr -e '\$rev -'.$repUpRev.'\$' *.html | xargs sed -i 's/'\$rev -'.$repUpRev.'\$'/'\$rev -.*$'/g'
It would help if you showed some input data.
The -r option makes the grep recursive. That means it will operate on files in the directory and its subdirectories. Is that what you intend?
The dots in your grep and sed stand for any character. If you want literal dots, you'll need to escape them.
The final escaped dollar sign in the grep and sed commands will be seen as a literal dollar sign. If you want to anchor to the end of the line you should remove the escape.
The .* works only as a literal string on the right hand side of a sed s command. If you want to include what was matched on the left side, you need to use capture groups. The g modifier on the s command is only needed if the pattern appears more than once in a line.
Using quote, unquote, quote, unquote is hard to read. Use double quotes to permit variable expansion.
Try your grep command by itself without the xargs and sed to see if it's producing a list of files.
This may be closer to what you want:
grep -lr -e "\$rev -.$repUpRev.$" *.html | xargs sed -i "s/\$rev -.$repUpRev.$/\$rev -REPLACEMENT_TEXT/g"
but you'll still need to determine if the g modifier, the dots, the final dollar signs, etc., are what you intend.

Resources