This question already has answers here:
How to grep for contents after pattern?
(8 answers)
Closed 4 years ago.
I need to get the IP from a log I need to grep the true-client and after that I need to grep true-client-ip=[191.168.171.15] and get just the IP
2019.02.14-08:26:06:713,asd:1234:chan,0.000,asd,S,request-begin-site,POST,{remoteHost=1.2.3.4,remoteAddr=1.2.3.4,requestType=POST,serverName=api=[text/html],accept-charset=[iso-12345-15, utf-8;q=0.5, *;q=0.5],accept-encoding=[gzip],server-origin=[5],cache-control=[no-cache, max-age=0],pragma=[no-cache],program-header=[true],te=[chunked;q=1.0],true-client-ip=[191.168.171.15],true-host=[www.server.com]
I was trying grep -o "true-client-ip=[^ ]*," but it brings me:
true-client-ip=[191.168.171.15],true-host=[www.server.com]
I need just true-client-ip=[191.168.171.15] so I can cut after to bring get the IP like true-client-ip=[191.168.171.15] | cut -d= -f2
Using grep -P flag if available :
grep -oP 'true-client-ip=\[\K[^]]*'
Perl's \K meta-character discards what precedes when displaying the result, so it will match the "true-client-ip=[" part but only display the IP.
If grep -P isn't available, I would use sed :
sed -nE 's/.*true-client-ip=\[([^]]*).*/\1/p'
If you have GNU grep, you can do it like this:
$ grep -oP "(?<=true-client-ip=\[)[^\]]*" file
191.168.171.15
The (?<=) is called Positive Lookbehind, which you can find related doc here.
The backslash \ in [^\]] is actually unnecessary, I just feel like to add it to make it more intuitive, less misleading-prone :-) .
Related
This question already has answers here:
How to get the second column from command output?
(8 answers)
Closed 3 years ago.
I am trying to get a specific output using grep but I am unable to do so.
Here is my grep command :
crictl inspect 47aaecb541688accf37840108cc0d19b39b84f8337740edf2ca7e5e81a24328e | grep "io.kubernetes.pod.namespace"
The output of the above command is "io.kubernetes.pod.namespace": "kube-system",
I even tried
crictl inspect 47aaecb541688accf37840108cc0d19b39b84f8337740edf2ca7e5e81a24328e | grep -Po '(?<="io.kubernetes.pod.namespace": ").*' but the output i got is kube-system",
I just want the value i.e just kube-system
How do I modify my grep command.
Thanks for the help
Using grep
We need to make just one small change to the grep -P command. Your command was:
$ echo '"io.kubernetes.pod.namespace": "kube-system",' | grep -Po '(?<="io.kubernetes.pod.namespace": ").*'
kube-system",
We just need to replace .* (which matches everything to the end of the line) with [^"]* with matches everything up to but not including the first ":
$ echo '"io.kubernetes.pod.namespace": "kube-system",' | grep -Po '(?<="io.kubernetes.pod.namespace": ")[^"]*'
kube-system
Or, using your crictl command:
crictl inspect 47aaecb541688accf37840108cc0d19b39b84f8337740edf2ca7e5e81a24328e | grep -Po '(?<="io.kubernetes.pod.namespace": ")[^"]*'
Using sed
$ echo '"io.kubernetes.pod.namespace": "kube-system",' | sed -n '/"io.kubernetes.pod.namespace"/{s/.*": "//; s/".*//p}'
kube-system
How it works:
-n tells sed not to print unless we explicitly ask it to.
/"io.kubernetes.pod.namespace"/{...} selects only those lines that contain "io.kubernetes.pod.namespace" and performs the commands in braces on them.
s/.*": "// removes everything from the beginning of the line to the last occurrence of ": ".
s/".*//p removes everything from the first remaining " to the end of the line and prints the result.
This question already has answers here:
shell script to extract text from a variable separated by forward slashes
(3 answers)
Closed 4 years ago.
I have this command in a script:
find /home/* -type d -name dev-env 2>&1 | grep -v 'Permiso' >&2 > findPath.txt
this gives me this back:
/home/user/project/dev-env
I need to take the second parameter between "/" (user) to save it later in a variable. I can not find the way to just pick up the "user" text.
Using cut:
echo "/home/user/project/dev-env" | cut -d'/' -f3
Result:
user
This tells cut to use / as the delimiter and return the 3rd field. (The 1st field is blank/empty, the 2nd field is home.)
Using awk:
echo "/home/user/project/dev-env" | awk -F/ '{print $3}'
This tells awk to use / as the field-seperator and print the 3rd field.
Assuming that the path resulting from the grep is always an absolute path:
second_component=$(find .... -type d -name dev-env 2>&1 | grep -v 'Permiso' | cut -d / -f 3)
However, your approach suffers from several other problems:
You use /home/* as starting point for find. This will work only, if there is exactly one subdirectory below /home. Not a very likely scenario.
Even then, it works only if grep results in exactly one line. This is a semantic problem: What if you get more than one line - which one are you interested in? Assume that you know that you are always interested into the first line, you can solve this by piping the result though head -n 1.
Next, you redirect the stderr from find to stdout, which means that any error from find remains unnoticed; you just get some weird result. It would be better to have any error message from find being displayed, and instead evaluate the exit code from find and grep.
... | cut -d/ -f3
"Third field, as cut by slash delimiter"
I am trying to see if my nohup file contains the words that I am looking for. If it does, then I need to put that into tmp file.
So I am currently using:
if grep -q "Started|missing" $DIR3/$dirName/nohup.out
then
grep -E "Started|missing" "$DIR3/$dirName/nohup.out" > tmp
fi
But it never goes into the if statement even if there are words that I am looking for.
How can I fix this?
Since basic sed uses BRE, regex alternation operator is represented by \| . | matches a literal | symbol. And you don't need to touch | symbol in the grep which uses ERE.
if grep -q "Started\|missing" $DIR3/$dirName/nohup.out
You should use egrep instead of grep (Avinash Raj has explained that in other words already in his answer).
I would generally recommend using egrep as a default for everyday use (even though many expressions only contain the basic regular expression syntax). From a practical point the standard grep is only interesting for performance reasons.
Details about the advantages of grep vs. egrep can be found in that superuser question.
When you only put the grep results into the tmp-file, you do not want to grep the file twice.
You can not use
egrep "Started|missing" $DIR3/$dirName/nohup.out > tmp
since that would create an empty tmp file when nothing is found.
You can remove empty files with if [ ! -s tmp ] or use another solution:
Redirectong the grep results without grepping again can be done with
rm -f tmp 2>/dev/null
egrep "Started|missing" $DIR3/$dirName/nohup.out | while read -r strange_line; do
echo "${strange_line}" >> tmp
done
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Use grep to report back only line numbers
I only want to see the line number. I don't need to see the remaining output.
Pipe your grep -n output, which normally looks something like:
11: stuff that matched
43: more stuff that matched
through sed to strip out the matching parts:
grep -n pattern file | sed -e 's/:.*//g'
11
43
grep -n or --line-number option will do this for you. You can find this information in the grep help file, which you can find by using grep --help or grep --help | less to read it more carefully. Also consider using the manual page: man grep
You could use awk too.
grep -n word file | awk -F: '{ print $1 }'
As #Barmar pointed out you could just use an awk one-liner as such:
awk '/regex/ { print NR }' file
Since you don't have awk you could also use cut:
grep -n word file | cut -d: -f1
I need to search for a PHP variable $someVar. However, Grep thinks that I am trying to run a regex and is complaining:
$ grep -ir "Something Here" * | grep $someVar
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
$ grep -ir "Something Here" * | grep "$someVar"
<<Here it returns all rows with "someVar", not only those with "$someVar">>
I don't see an option for telling grep not to interpret the string as a regex, but to include the $ as just another string character.
Use fgrep (deprecated), grep -F or grep --fixed-strings, to make it treat the pattern as a list of fixed strings, instead of a regex.
For reference, the documentation mentions (excerpts):
-F --fixed-strings Interpret the pattern as a list of fixed
strings (instead of regular expressions), separated by newlines, any
of which is to be matched. (-F is specified by POSIX.)
fgrep is the same as grep -F. Direct invocation as fgrep is
deprecated, but is provided to allow historical applications that rely
on them to run unmodified.
For the complete reference, check:
https://www.gnu.org/savannah-checkouts/gnu/grep/manual/grep.html
grep -F is a standard way to tell grep to interpret argument as a fixed string, not a pattern.
You have to tell grep you use a fixed-string, instead of a pattern, using '-F' :
grep -ir "Something Here" * | grep -F \$somevar
In this question, the main issue is not about grep interpreting $ as a regex. It's about the shell substituting $someVar with the value of the environment variable someVar, likely the empty string.
So in the first example, it's like calling grep without any argument, and that's why it gives you a usage output. The second example should not return all rows containing someVar but all lines, because the empty string is in all lines.
To tell the shell to not substitute, you have to use '$someVar' or \$someVar. Then you'll have to deal with the grep interpretation of the $ character, hence the grep -F option given in many other answers.
So one valid answer would be:
grep -ir "Something Here" * | grep '$someVar'
+1 for the -F option, it shall be the accepted answer.
Also, I had a "strange" behaviour while searching for the -I.. pattern in my files, as the -I was considered as an option of grep ; to avoid such kind of errors, we can explicitly specify the end of the arguments of the command using --.
Example:
grep -HnrF -- <pattern> <files>
Hope that'll help someone.
Escape the $ by putting a \ in front of it.