0

let's say I have:

variable=string

and now would like to replace use brackets for the first letter

${variable/firstletter/[firstletter]}

Finally I want to use it in the script to modify a regex pattern so that it doesn't match itself:

ps -e -o time,user,pid,ppid,comm,args | grep ${variable/firstletter/[firstletter]}

I'd like to use it instead of additional pipe and grep -v grep or pgrep

Also, maybe you know how to achieve such process grep with awk and not print awk command itself?

  • Are the typos of variable to varaible real or copy:paste? – Jeff Schaller Feb 6 '18 at 15:56
  • 2
    Do you have pgrep available? – Jeff Schaller Feb 6 '18 at 16:20
  • 1
    Why do you not want to use pgrep? – Kusalananda Feb 6 '18 at 16:39
3

You just need to grab the first character of your parameter, to wrap in brackets, then add the rest back:

bash-[508]$ variable=string
bash-[509]$ echo $variable
string
bash-[510]$ echo $variable to [${variable:0:1}]${variable:1}
string to [s]tring

So your command might be something like:

ps -e -i time,user,pid,ppid,comm,args | grep "[${variable:0:1}]${variable:1}"

This is using bash parameter substitution on ranges of characters in a variable, given as where to start, and how long the grab should be.

${variable:0:1}, starts at character 0, the start of the string, and grabs 1 character. Thus isolating the first letter, v.

${variable:1}, then starts at character 1, and without a defined range, grabs everything up to the end of $variable, grabbing ariable.

1

I have just such a function in my .bashrc, except I can take multiple search patterns:

psg () {
    local -a patterns=()
    (( $# == 0 )) && set -- $USER
    for arg in "$@"; do
        patterns+=("-e" "[${arg:0:1}]${arg:1}");
    done
    ps -ef | grep --color=auto "${patterns[@]}"
}

and yes, I know pgrep exists.

$ psg fish bash vim grep
glennj       2     1 67 09:00 ?        02:32:31 fish
glennj     153     1  0 09:00 tty2     00:00:06 fish
glennj    3122     1  0 11:08 tty3     00:00:07 fish
glennj    3964   153  0 12:14 tty2     00:00:00 vim supersecretfile
glennj    4992  3122  0 12:41 tty3     00:00:00 bash
glennj    5162  4992  0 12:45 tty3     00:00:00 grep --color=auto -e [f]ish -e [b]ash -e [v]im -e [g]rep
  • that's a great idea. my .bashrc will have a very similar function in just a couple of minutes. :D – Tim Kennedy Feb 6 '18 at 22:02
0

Please try:

#!/bin/sh 

variable=rsyslogd

regex="[$(expr "$variable" : '\(.\)')]""${variable#?}"
echo "$regex"
ps -e -o time,user,pid,ppid,comm,args | grep '$regex'

Testing:

$ ./script
[r]syslogd
00:00:00 root       521     1 rsyslogd        /usr/sbin/rsyslogd -n

This might fail if the first character of variable is special \ [ ] * ? etc.

0

maybe you know how to achieve such process grep with awk and not print awk command itself?

With GNU awk, we could exclude the awk process itself by using PROCINFO to get the script's PID.

$ pattern=cron
$ ps -e -o time,user,pid,ppid,comm,args  |
  gawk -vpat="$pattern" 'NR == 1 || $3 != PROCINFO["pid"] && $0 ~ pat' 
    TIME USER       PID  PPID COMMAND         COMMAND
00:00:10 root       530     1 cron            /usr/sbin/cron -f

Change $0 ~ pat to index($0, pat) to implement a fixed-string match instead of a regex match.

Though of course, you could use pgrep in combination with ps:

$ ps -o time,user,pid,ppid,comm,args $(pgrep "$pattern")
    TIME USER       PID  PPID COMMAND         COMMAND
00:00:10 root       530     1 cron            /usr/sbin/cron -f

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.