I have a string, "$server['fish_stick']" (disregard double quotes)
I don't know how to successfully grep for an exact match for this string. I've tried many ways.
I've tried,
rgrep -i \$'server'\[\''fish'\_'stick'\'\] .
rgrep -i "\$server\[\'fish\_stick\'\]" .
rgrep -i '\$server\[\'fish\_stick\'\]' .
Is it single quotes that are causing my issue?
When I echo the first grep out it shows exactly what I want to search but returns garbage results like anything with $server in it.
Please help and explain, thank you!
The main problem here is that you are not quoting the argument being passed to grep. The only thing that needs to be escaped is \$ (if double quoted) and []. If you want the exact string (not using regex), just use fgrep (grep -F) which does exact string matching:
grep -F "\$server['fish_stick']"
Works on my system:
$ foo="\$server['fish_stick']"
$ echo "$foo" | grep -F "\$server['fish_stick']"
$server['fish_stick']
Using regex:
$ echo "$foo" | grep "\$server\['fish_stick'\]"
$server['fish_stick']
Using regex and handling nested single quotes:
$ echo "$foo" | grep '\$server\['\''fish_stick'\''\]'
$server['fish_stick']
Inside of single quotes, nested single quotes can not be not be escaped. You have to close the quotes, and then reopen it to "escape" the single quotes.
http://mywiki.wooledge.org/Quotes
I don't suppose you're asking how to get that string into a variable without having quoting issues. If you are, here's a way using a here-document:
str=$(cat <<'END'
$foo['bar']
END
)
To address your concern about escaping special characters for grep, you could use sed to put a backslash before any non-alphanumeric character:
grep "$(sed 's/[^[:alnum:]]/\\&/g' <<< "$str")" ...
When used with set -x, the grep command looks like: grep '\$foo\[\'\''bar\'\''\]' ...
Related
I need to find in a log, all lines containing a server name.
So I do in my script :
grep $x ./input_log_files.csv >> test.txt
where x contain the server name.
The problem is that this way, I also trap lines that contain the server name in a longer name. To be clear, we have here a AIXserver, and also a virtual server called VAIXserver. So when I search the first one, I get the other one too.
In my log file, the server name in surrounded by double quotes. I'm desperately trying to grep on the server name WITH the double quotes. I also tryed with the commas such as in ,"AIXserver", with no success.
How can I force grep to consider the double quotes ?
I tryed with singl quotes, escape characters ... with no success.
Thx for your help.
B²
grep -w $x ./input_log_files.csv >> test.txt
alternate option
perl -ne 'print if /\b$x\b/' ./input_log_files.csv >> test.txt
Make sure the variable contains the quotes:
x='"sname"'
And use it quoted:
$ testval=$'sname\nVsname\n"sname"\n"Vsname"\n"sname2"'
$ echo "$testval"
sname
Vsname
"sname"
"Vsname"
"sname2"
$ echo "$testval" | grep "$x"
"sname"
For your command line:
grep "$x" ./input_log_files.csv >> test.txt
I'm trying to search for
Assembly="Foobar
in all files and direct the output to tmp.txt
I've tried (cmd/error)
grep -r "Assembly=\"Foobar" . >> tmp.txt
error (invalid argument)
grep -r "Assembly=""Foobar" . >> tmp.txt
error (not enough space)
grep -r 'Assembly="Foobar' . >> tmp.txt
error (not enough space)
very frustrating. Any suggestions?
You need to worry about escaping quotes for both grep and cmd.exe
grep expects quotes to be escaped as \"
cmd.exe escapes quotes as ^". The quote is a state machine, meaning unescaped quotes toggle quote semantics on and off. When quoting is on, special characters like <, |, &, etc are treated as literals. The first unescaped quote turns on quote semantics. The next quote turns quote semantics off. It is only possible to escape a quote when quoting is OFF. Unbalanced quotes result in the remainder being quoted. So in your case, the >>tmp.txt is not treated as redirection by cmd.exe, so it gets passed to grep as an argument.
Any of the following will work:
grep -r "Assembly=\"Foobar^" . >>tmp.txt
grep -r ^"Assembly=\"Foobar" . >>tmp.txt
grep -r ^"Assembly=\^"Foobar^" . >>tmp.txt
grep -r Assembly=\^"Foobar . >>tmp.txt
If your search term included spaces, then grep needs the enclosing quotes, so you would need any of the first three forms. The last form would not work with spaces in the search term.
I'm trying to use a variable in a grep regex. I'll just post an example of the failure and maybe someone can suggest how to make the variable be evaluated while running the grep command. I've tried ${var} as well.
$ string="test this"
$ var="test"
$ echo $string | grep '^$var'
$
Since my regex should match lines which start with "test", it should print the line echoed thru it.
$ echo $string
test this
$
You need to use double quotes. Single quotes prevent the shell variable from being interpolated by the shell. You use single quotes to prevent the shell from doing interpolation which you may have to do if your regular expression used $ as part of the pattern. You can also use a backslash to quote a $ if you're using double quotes.
Also, you may need to put your variable in curly braces ${var} in order to help separate it from the rest of the pattern.
Example:
$ string="test this"
$ var="test"
$ echo $string | grep "^${var}"
I need to find some special characters in a given input string .
If the string contains following special characters it should find out.
i am doing egrep to find the characters.
My code is working for every character but not single quotes.
please find my code snippet.
splCharCheck='egrep "&|\"|:|\'" | wc -l'
count=`echo "$Name" | eval $splCharCheck`
Can any one help me how to escape single quotes here?
Don't "escape" the single quote. Check below:
# cat test
'name with quotes'
no quotes
# cat test | egrep "'"
'name with quotes'
# cat test | egrep "\'"
'name with quotes'
no quotes
What are you trying to achieve? This smells like an XY problem.
In bash you can escape text easily using
printf "%q\n" "$Name"
E.g.:
$ Name="Some 'intricate' value"
$ printf "%q\n" "$Name"
Some\ \'intricate\'\ value
You're trying to embed a single-quote inside a double-quoted string which is inside a single-quoted string. The problem is that inside the single-quoted string, the double-quotes aren't treated as anything special, so the single-quote in the middle gets treated as the end of the single-quoted string rather than a part of it. In order to do this, you need to end the single-quoted string ('egrep "&|\"|:|'), escape the lone single-quote some other way (either \' or "'"), then start a new single-quoted string with the rest of what you want ('" | wc -l'). End result:
splCharCheck='egrep "&|\"|:|'\''" | wc -l'
However, I have to agree with #sehe that it looks like you're trying to solve the wrong problem. Why are you putting this command in a variable rather than executing it directly? That's generally a bad idea (and eval just adds more opportunities for things to get weird). And, backing up even further, what are you really trying to do?
p.s. If you must use eval, at least double-quote the string your're eval'ing. Failing to do this can lead to some seriously incomprehensible errors. Finally, I recommend using $( ) instead of backquotes, since it has fewer parsing oddities:
count=$(echo "$Name" | eval "$splCharCheck")
I need to egrep a string that isn't known before runtime and that I'll get via shell variable (shell is bash, if that matters). Problem is, that string will contain special characters like braces, spaces, dots, slashes, and so on.
If I know the string I can escape the special characters one at a time, but how can I do that for the whole string?
Running the string through a sed script to prefix each special character with \ could be an idea, I still need to rtfm how such a script should be written. I don't know if there are other, better, options.
I did read re_format(7) but it seems there is no such thing like "take the whole next string as literal"...
EDIT: to avoid false positives, I should also add newline detection to the pattern, eg. egrep '^myunknownstring'
If you need to embed the string into a larger expression, sed is how I would do it.
s_esc="$(echo "$s" | sed 's/[^-A-Za-z0-9_]/\\&/g')" # backslash special characters
inv_ent="$(egrep "^item [0-9]+ desc $s_esc loc .+$" inventory_list)"
Use the -F flag to make the PATTERN a fixed literal string
$ var="(.*+[a-z]){3}"
$ echo 'foo bar (.*+[a-z]){3} baz' | grep -F "$var" -o
(.*+[a-z]){3}
Are you trying to protect the string from being incorrectly interpreted as bash syntax or are you trying to protect parts of the string from being interpreted as regular expression syntax?
For bash protection:
grep supports the -f switch:
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file contains zero patterns, and therefore matches nothing.
No escaping is necessary inside the file. Just make it a file containing a single line (and thus one pattern) which can be produced from your shell variable if that's what you need to do.
# example trivial regex
var='^r[^{]*$'
pattern=/tmp/pattern.$$
rm -f "$pattern"
echo "$var" > "$pattern"
egrep -f "$pattern" /etc/password
rm -f "$pattern"
Just to illustrate the point.
Try it with -F instead as another poster suggested for regex protection.