How can you set a variable as the output of a command and then use that variable later in the same command on linux? - linux

I want to have a single command, not a script, that I can use to define a variable as a command output and then put that output into other commands. My best guess as to what that would look like is this:
LIST=$(ls) | head -1 | echo "${LIST}"
One reason that I want to do this is so that I can create a command that can find the pid of a program and then kill that pid. My best try doing that is:
DiscPid=$(ps -e | grep Discord | cut -b 1-5 | head -1 \ ) | kill "${DiscPid}"
But I'm not able to get this to work
I'm still relatively new to Linux and Bash so any help would be appreciated

Use a semicolon after setting the variable: var=foo; echo $var

You don't need piping here
DiscPid=$(code) | kill "${DiscPid}"
Change '|' to ';' and this one '\' also spare
DiscPid=$(ps -e | grep Discord | cut -b 1-5 | head -1); kill "${DiscPid}"

Related

cat: pid.txt: No such file or directory

I have a problem with cat. I want to write script doing the same thing as ps -e. In pid.txt i have PID of running processes.
ls /proc/ | grep -o "[0-9]" | sort -h > pid.txt
Then i want use $line like a part of path to cmdline for evry PID.
cat pid.txt | while read line; do cat /proc/$line/cmdline; done
i try for loop too
for id in 'ls /proc/ | grep -o "[0-9]\+" | sort -h'; do
cat /proc/$id/cmdline;
done
Don't know what i'm doing wrong. Thanks in advance.
I think what you're after is this - there were a few flaws with all of your approaches (or did you really just want to look at process with a single-digit PID?):
for pid in $(ls /proc/ | grep -E '^[0-9]+$'|sort -h); do cat /proc/${pid}/cmdline; tr '\x00' '\n'; done
You seem to be in a different current directory when running cat pid.txt... command compared to when you ran your ls... command. Run both your commands on the same terminal window, or use absolute path, like /path/to/pid.txt
Other than your error, you might wanna remove -o from your grep command as it gives you 1 digit for a matching pid. For example, you get 2 when pid is 423. #Roadowl also pointed that already.

Why doesn't the pipeline take effect in bash in Linux?

Here is to count the number of sessions by the same login user.
I could run the direct command if I know the specific user name, such as usera, as the following:
who | grep usera | wc -l
And if I don't know the current user, I need to user parameter.
But the following codes don't work:
currentuser=`whoami`
sessionnumber=`who | grep "$currentuser" | wc -l`
What's the error?
Thanks!
Grep has the -c flag so the wc -l plus the additional pipe is not needed.
who | grep -c -- "$USER"
"$LOGNAME" is also an option instead of "$USER", which one is bash specific? I don't know, all I know is that they are both on Linux and FreeBSD system. The -- is just a habit just in case the user starts with a dash grep will not interpret it as an option.
sessionnumber=`who | grep "$currentuser" | wc -l`
You are assigning the result of the who | ... command to a variable and to see its value you can use echo $sessionnumber
Looks like you are confused about parameters and variables.
What you are trying to get is likely
who | grep $(whoami) | wc -l
The $() is equivalent to the backticks you used.
When you write
sessionnumber=``
this will run whatever is within the backticks and save the output to a variable. You can then access the variable using the dollar notation:
echo "$sessionnumber"

Grep into variable and maintain stdout?

I've got a long running process and I want to capture a tiny bit of data from the big swath of output.
I can do this by piping it through grep, but then I can't watch it spew out all the other info.
I basically want grep to save what it finds into a variable and leave stdout alone. How can I do that?
With tee, process substitution, and I/O redirection:
{ var=$(cmd | tee >(grep regexp) >&3); } 3>&1
There isn't any way to use a variable like that. It sounds like you want to write your own filter:
./some_long_program | tee >(my_do_stuff.sh)
Then, my_do_stuff.sh is:
#!/bin/bash
while read line; do
echo "$line" | grep -q 'pattern' || continue
VARIABLE=$line # Now it's in a variable
done
If you have the storage space, this is probably more like what you want:
./some_long_program | tee /tmp/slp.log
Then, simply:
grep 'pattern' /tmp/slp.log && VARIABLE=true
or:
VARIABLE=$(grep 'pattern' /tmp/slp.log)
This will let you run the grep at any time. I don't think the variable really adds anything though.
EDIT:
#mpen Based on your last answer above, it sounds like you want to use xargs. Try:
(echo 1 ; sleep 5 ; echo 2) | xargs -L1 echo got:
The -L1 will run the command for every instance found, otherwise it grabs lots of stdin and passes them all (up to some maximum) to the command at once. You'll still want to use this via tee if you want to see all the command output as well:
./some_long_program | tee >(grep 'pattern' | xargs -L1 ./my_do_stuff.sh)
I think this can be done a little more simply if we tee to /dev/tty:
❯ BAR=$(echo foobar | tee /dev/tty | grep -Pom1 b..); echo "[$BAR]"
foobar
[bar]

Unsing integer Variable to process linux cut command fields

The following command below does not succeed.
for i in {1..5} ; do cat /etc/fstab | egrep "(ext3|ext4|xfs)" | awk '{print $2}' | cut -d"/" -f1-$i ; done
It seems that $i is ignored completely. It always returns instead result of
cut -d"/" -f1-
Any idea why it fails?
Thanks in advance!
The command itself is a part of a script that should help me to auto re-arrange fstab lines to match the right mount order (like /test/subfolder must come after /test was mounted and not before).
I tried and it didn't work for zsh shell. BUT I tried it in bash and it does work, so if you are using zsh just run the command with bash and it should work ;)

How to grep both header and pattern with grep

I need to grep both header and also particular pattern only using grep,
eg
for command "ps"
output
PID TTY TIME CMD
10280 pts/16 00:00:00 ps
32463 pts/16 00:00:00 bash
how can i grep both header and pattern like 32463 so output should be
PID TTY TIME CMD
32463 pts/16 00:00:00 bash
And One thing is that solution should be general that means it should be applicable to all commands that have headers
Try this:
ps | head -1; ps | grep bash
Like this:
ps | ( read -r head; printf '%s\n' "$head"; grep bash )
This generalizes to other commands, such as
( read -r head; printf '%s\n' "$head"; sort -k4n ) <input.csv >input-sorted-4n.csv
You could encapsulate this into a script called keepheader:
#!/bin/sh
read -r head
printf '%s\n' "$head"
exec "$#"
Use like
ps | keepheader grep bash
keepheader sort -k4n <input.csv >input-sorted-4n.csv
or maybe even
keepheader keepheader grep foo <<HERE
Header with underlines
------ ---- ----------
Cat food Whiskas
Mouse bait Cheese
HERE
(Actually maybe make the script accept an optiinal numeric parameter to specify how many header lines to keep; I leave this as an exercise for the reader.)
I suggest sed:
sed -n "1p;/$pattern/p"
how can i grep both header and pattern
You could try this
ps | grep -e 'PID\|32463'
solution should be general that means it should be applicable to all commands that have headers
This requirement is almost impossible to satisfy by grep, because different commands have different headers, it is impossible to assign a regular expression to match all of them.
But you could use the following command to achieve your goal:
command | perl -e 'while(<STDIN>) { print if $. == 1 or m/$ARGV[0]/ }' pattern
If it is too cumbersome for daily use, you can put it in a custom script, such as my-grep, and put that script in your $PATH, then you can use that script like a normal command:
command | my-grep pattern
With out using grep you can get this output for ps option
$ps -p 32463
-p Select by PID.
This selects the processes whose process ID numbers appear in pidlist. Identical to p and --pid.

Resources