I'm trying to understand how to use special characters in grep and wc [duplicate] - linux

This question already has an answer here:
Reference - What does this regex mean?
(1 answer)
Closed 6 years ago.
Can you explain in detail what happened here on this command?
grep -nw '^root' /etc/passwd
What is the use of ^ and '? Please give me examples and be detailed cuz all I'm hearing is that it's the beginning of the line. I don't understand what each of those special characters means.
How would I go about using wc, grep and ^ to find out the number of non-root processes running on my system?

grep -nw '^root' /etc/passwd
It reads the /etc/passwd file line-by-line and filters out all those lines that ^=begin with the -w=complete word "root". So, for example the line
root:x:0:0:root:/root:/bin/bash
To see all processes on a system, you could use ps aux. and it will show lines like this
root 22866 0.0 [...] 0:00 [kworker/1:0]
As you can see, the lines start with a username. If you pipe the ps aux output through grep, you can use the same RegEx from above, to filter out all lines that do not start with "root".
Use -v to invert pattern matching, so that grep -vw '^root' finds all lines that don't begin with a complete word "root".
ps aux | grep -vw '^root' | wc -l
Finally, wc -l counts the number of lines it receives. So that is the number of all lines from ps aux that do not begin with "root".

Related

grepping output of ps, exclude the word grep [duplicate]

This question already has answers here:
More elegant "ps aux | grep -v grep"
(9 answers)
Closed 3 years ago.
I'm using ps to find the pid of a process created to execute the command "sleep 1234 &"
I grep the result to match only "sleep 1234".
ps -A -f | grep "sleep 1234"
however, this matches also the command "grep sleep 1234" itself, returning two lines instead of one. How do I write a pattern for grep to exclude the word 'grep' itself?
Thanks
This is a pretty common problem and the easiest solution is to just surround a character in the grep'ed pattern with square brackets:
ps -A -f | grep "[s]leep 1234"
This will now match sleep 1234, but not [s]leep 1234 (because of the literal ] between s and l), and the grep line no longer matches.
The reason that the grep is in the process list is that pipelines are executed from right to left, so the grep is actually executed prior to the ps.

num = 'ps -ef | grep -v grep| grep BatchName| wc -l' [duplicate]

This question already has an answer here:
UNIX grep command (grep -v grep)
(1 answer)
Closed 7 years ago.
I am having the basic knowledge of Unix. I'm programming for a wrapper script but in the above line of code I'm not getting the meaning and output of "grep -v grep". Please explain that in detail. Try to explain requested part only, it would be great help.
Thanks
It's excluding the grep process from the results, that's it. Run
grep --help
And you'll see
-v, --invert-match select non-matching lines
So the line
xxxx 27731 27613 0 17:21 pts/14 00:00:00 grep --color=auto /bin/bash
won't be returned as a result since we excluded "grep".

display all the ssh pids where the users are connected to in one line [duplicate]

This question already has answers here:
How to join multiple lines of filenames into one with custom delimiter
(22 answers)
Closed 7 years ago.
How can I display all the ssh pids where the users are connected to in one line separated by comma ?
This command displays the output in multiple lines, I would like to have the output in one line.
ps aux | grep -i "ssh" | awk '{print $2}'
from
1325
3255
2323
5321
3252
To
1325, 3255, 2323, 5321, 3252
Thank You!
You may want to use pgrep to get the processes IDs directly:
$ pgrep ssh
1217
5305
This way, you avoid calling ps aux and parsing its output, which will always contain the grep itself.
To join them on a ,-separated list, use paste on a -serial mode:
$ pgrep ssh | paste -s -d,
1217,5305
You could use sed utility in another pipe, so the command would be:
ps aux | grep -i "ssh" | awk '{print $2}' | sed ':a;{N;s/\n/, /};ba'
Where you are in fact replacing new lines (except the final one) by commas.

How to capture the output of a bash command into a variable when using pipes and apostrophe? [duplicate]

This question already has answers here:
How do I set a variable to the output of a command in Bash?
(15 answers)
Closed 6 years ago.
I am not sure how to save the output of a command via bash into a variable:
PID = 'ps -ef | grep -v color=auto | grep raspivid | awk '{print $2}''
Do I have to use a special character for the apostrophe or for the pipes?
Thanks!
To capture the output of a command in shell, use command substitution: $(...). Thus:
pid=$(ps -ef | grep -v color=auto | grep raspivid | awk '{print $2}')
Notes
When making an assignment in shell, there must be no spaces around the equal sign.
When defining shell variables for local use, it is best practice to use lower case or mixed case. Variables that are important to the system are defined in upper case and you don't want to accidentally overwrite one of them.
Simplification
If the goal is to get the PID of the raspivid process, then the grep and awk can be combined into a single process:
pid=$(ps -ef | awk '/[r]aspivid/{print $2}')
Note the simple trick that excludes the current process from the output: instead of searching for raspivid we search for [r]aspivid. The string [r]aspivid does not match the regular expression [r]aspivid. Hence the current process is removed from the output.
The Flexibility of awk
For the purpose of showing how awk can replace multiple calls to grep, consider this scenario: suppose that we want to find lines that contain raspivid but that do not contain color=auto. With awk, both conditions can be combined logically:
pid=$(ps -ef | awk '/raspivid/ && !/color=auto/{print $2}')
Here, /raspivid/ requires a match with raspivid. The && symbol means logical "and". The ! before the regex /color=auto/ means logical "not". Thus, /raspivid/ && !/color=auto/ matches only on lines that contain raspivid but not color=auto.
A more straightforward approach:
pid=$(pgrep raspivid)
... or a little different
echo pgrep [t]eleport

Preserve colouring after piping grep to grep

There is a simlar question in Preserve ls colouring after grep’ing but it annoys me that if you pipe colored grep output into another grep that the coloring is not preserved.
As an example grep --color WORD * | grep -v AVOID does not keep the color of the first output. But for me ls | grep FILE do keep the color, why the difference ?
grep sometimes disables the color output, for example when writing to a pipe. You can override this behavior with grep --color=always
The correct command line would be
grep --color=always WORD * | grep -v AVOID
This is pretty verbose, alternatively you can just add the line
alias cgrep="grep --color=always"
to your .bashrc for example and use cgrep as the colored grep. When redefining grep you might run into trouble with scripts which rely on specific output of grep and don't like ascii escape code.
A word of advice:
When using grep --color=always, the actual strings being passed on to the next pipe will be changed. This can lead to the following situation:
$ grep --color=always -e '1' * | grep -ve '12'
11
12
13
Even though the option -ve '12' should exclude the middle line, it will not because there are color characters between 1 and 2.
The existing answers only address the case when the FIRST command is grep (as asked by the OP, but this problem arises in other situations too).
More general answer
The basic problem is that the command BEFORE | grep, tries to be "smart" by disabling color when it realizes the output is going to a pipe. This is usually what you want so that ANSI escape codes don't interfere with your downstream program.
But if you want colorized output emanating from earlier commands, you need to force color codes to be produced regardless of the output sink. The forcing mechanism is program-specific.
Git: use -c color.status=always
git -c color.status=always status | grep -v .DS_Store
Note: the -c option must come BEFORE the subcommand status.
Others
(this is a community wiki post so feel free to add yours)
Simply repeat the same grep command at the end of your pipe.
grep WORD * | grep -v AVOID | grep -v AVOID2 | grep WORD

Resources