How to set permanent alias - linux

Can anybody help me to set following script as alias:
ps axu | awk '{print $2, $3, $4, $11}' | head -1 && ps axu | awk '{print $2, $3, $4, $11}' | sort -k3 -nr |head -20
I tried adding below line .bashrc file
alias abc='ps axu | awk '{print $2, $3, $4, $11}' | head -1 && ps axu | awk '{print $2, $3, $4, $11}' | sort -k3 -nr |head -20'
But had no luck, I am getting below error
$abc
Usage: grep [OPTION]... PATTERN [FILE]... sort: read failed: /apps/: Is a directory Try 'grep --help' for more information.

Here's a tip: don't call ps twice: pipe the output to a group of commands. As a function, you'll have much less quoting grief.
abc() {
ps axu | awk '{print $2, $3, $4, $11}' | {
IFS= read -r header && echo "$header" # the first line
sort -k3 -nr | head -20 # all the rest
}
}

The command ps is very configurable. This two commands are almost equivalent, your selection by awk, and a configured ps format:
ps axu | awk '{print $2, $3, $4, $11}'
ps axopid,pcpu,pmem,comm
Where the user u formatting was replaced by an special format o pid,pcpu,pmem,cmd. Is is similar, not identical only because of the command name and some formatting. We will get to that a bit later.
If the command name is not a deal breaker, ps could even sort by some selected key with the k option, and selecting only 20 lines we get:
ps axopid,pcpu,pmem,comm k-pmem | head -20
Which replace all the selecting, sorting, and formatting of your initial command. That should be enough for all practical uses I think.
But if you do need an identical output as your original, we need to expand the command to show all args. Such output is very long for some commands and doesn't format well. Additionally, the awk processing you used could NOT be reproduced by plain ps. We need to cut the command part in the first space and, to get a better formatting we need some printf love.
All said, this gets exactly the same output (well, a bit better formatted):
ps axopid,pcpu,pmem,cmd k-pmem | head -20 | awk '
{gsub(/ .*/, "", $4); printf "%5s %4s %4s %-.50s\n", $1,$2,$3,$4}'
And, just making it a single line to make its use a little easier to copy/paste:
ps axopid,pcpu,pmem,cmd k-pmem | head -20 | awk '{gsub(/ .*/, "", $4); printf "%5s %4s %4s %-.50s\n", $1,$2,$3,$4}'
And so, the alias becomes only one line.
I hope you will be able to get the alias working.

I don't know where grep is coming from but your problem is that quotes don't nest like that.
When you stuck the single quoted awk scripts inside single quotes for the alias the quotes match-up incorrectly.
Replace each "inner" single quote with '\'' and it should work.
alias abc='ps axu | awk '\''{print $2, $3, $4, $11}'\'' | head -1 && ps axu | awk '\''{print $2, $3, $4, $11}'\'' | sort -k3 -nr |head -20'

Related

declare variables in the same line shell script

Below is a part of my script where I used different lines for different variable.In the first two lines command used is similar though not same , is there a way to reduce these five lines:
oldv=$( sed -n "${c}p" ~/grepoutput | awk '{print $3 }')
line=$(sed -n "${c}p" ~/grepoutput | awk -F":" '{print $2 }')
newv=$( sed -n "${c}p" ~/vpkglist | awk '{print $3 }' )
oldr=$( sed -n "${c}p" ~/vpkglist | awk '{print $4 }' )
newr=$( sed -n "${c}p" ~/vpkglist | awk '{print $5 }' )
In the first two lines it`s 'grepoutput' is the same file and bottom three lines 'vpkglist' remains same.

How to split string with awk using '\t|' sting as a separator?

I am trying to split the string using custom field separator like this:
$ echo -e "abc\t|def" | awk -F '\t|' '{print $1, $2}'
abc |def
I expect output to be:
abc def
But instead it also includes | character which is part of separator:
abc |def
If using '\t#' as a separator I am getting expected output:
$ echo -e "abc\t#def" | awk -F '\t#' '{print $1, $2}'
abc def
So by some reason | character in field separator does not work as expected.
How can I make it work ?
It should be:
awk -F '\t[|]' '{print $1, $2}'
-F will get evaluated as a regex. Put the | into a character class since it has special meaning in the regex.
Alternatively you can use:
awk -F '\t\\|' '{print $1, $2}'

Trying to join output from ps and pwdx linux commands

I am trying to join output from ps and pwdx command. Can anyone point out the mistake in my command.
ps -eo %p,%c,%u,%a --no-headers | awk -F',' '{ for(i=1;i<=NF;i++) {printf $i",
"} ; printf pwdx $1; printf "\n" }'
I expect the last column in each row to be the process directory. But it just shows the value of $1 instead of the command output pwdx $1
This is my output sample (1 row):
163957, processA , userA , /bin/processA -args, 163957
I expected
163957, processA , userA , /bin/processA -args, /app/processA
Can anyone point out what I may be missing
Try this:
ps -eo %p,%c,%u,%a --no-headers | awk -F',' '{ printf "%s,", $0; "pwdx " $1 | getline; print gensub("^[0-9]*: *","","1",$0);}'
Explanation:
awk '{print pwdx $1}' will concatenate the awk variable pwdx (which is empty) and $1 (pid). So, effectively, you were getting only the pid at the output.
In order to run a command and gets its output, you need to use this awk construct:
awk '{"some command" | getline; do_something_with $0}'
# After getline, the output will be present in $0.
#For multiline output, use this:
awk '{while ("some command" | getline){do_something_with $0}}'
# Each individual line will be present in subsequent run of the while loop.
Simplifying your example to focus on how to execute the pwdx command within awk and capture the result of this command into an awk variable as this is where you were having issues:
ps -eo %p,%c,%u,%a --no-headers | awk -F',' '{ system("pwdx "$1) | getline vpwdx; printf vpwdx $1}'
produces:
15651665: /
16651690: /
16901691: /home/fpm
169134248: /home/fpm
3424834254: /home/fpm/tmp
3425440181: /home/fpm/UDK2015
...

Extract text with any command in linux shell

How do I extract the text from the following text and store it to the variables:
05:21-09:32, 14:21-19:30
Here, I want to store 05 in one variable, 21 in another, 09 in another and so on. All the value must me stored in array or in separate varibles.
I have tried:
k="05:21-09:32, 14:21-19:30"
part1=($k | awk -F"-" '{print $1}' | awk -F":" '{print $1}')
part2=($k | awk -F"-" '{print $2}' | awk -F":" '{print $1}')
part3=($k | awk -F"," '{print $2}' | awk -F":" '{print $1}')
part4=($k | awk -F"-" '{print $3}' | awk -F":" '{print $1}')
I need a more clear solution or short solution.
You can use read with the -array option:
IFS=':-, ' read -ra my_arr <<< "05:21-09:32, 14:21-19:30"
The above code will split the input string on :, -, , and spaces:
$ echo "${my_arr[0]}" "${my_arr[1]}" "${my_arr[2]}" "${my_arr[3]}"
05 21 09 32
Your code has a number of problems.
You can't pipe the value of k to standard output with just $k -- you want something like printf '%s\n' "$k" or perhaps the less portable echo "$k"
Notice also the quoting in the expression above; without it, the shell will perform wildcard expansion and whitespace tokenization on the value
Spawning two Awk processes for a simple string substitution is excessive
Spawning a separate pipeline for each value you want to extract is inefficient; if at all possible, extract everything in one go.
Something like IFS=':-, '; set -- $k will assign the parts to $1, $2, $3, and $4 in one go.

Unix/Linux Shell Grep to cut

I have a file, say 'names' that looks like this
first middle last userid
Brian Duke Willy willybd
...
whenever I use the following
line=`grep "willybd" /dir/names`
name=`echo $line | cut -f1-3 -d' '`
echo $name
It prints the following:
Brian Duke Willy willybd
Brian Duke Willy
My question is, how would I get it to print just "Brian Duke Willy" without first printing the original line that I cut?
The usual way to do this sort of thing is:
awk '/willybd/{ print $1, $2, $3 }' /dir/names
or, to be more specific
awk '$4 ~ /willybd/ { print $1, $2, $3 }' /dir/names
or
awk '$4 == "willybd" { print $1, $2, $3 }' /dir/names
grep "willybd" /dir/names | cut "-d " -f1-3
The default delimiter for cut is tab, not space.
Unless you need the intermediate variables, you can use
grep "willybd" /dir/names | cut -f1-3 -d' '
One of the beautiful features of linux is that most commands can be used as filters: they read from stdin and write to stdout, which means you can "pipe" the output of one command into the next command. That's what the | character does. It's pronounced pipe.

Resources